Προγραμματισμός

SAAJ: Δεν επισυνάπτονται συμβολοσειρές

Τη στιγμή αυτής της γραφής, οι περισσότερες υπηρεσίες Web αποτελούνται από απλές ανταλλαγές μηνυμάτων: Ένας πελάτης επικοινωνεί με μια υπηρεσία Web και στέλνει ένα μήνυμα σε αυτήν την υπηρεσία. Η υπηρεσία Web, με τη σειρά της, επεξεργάζεται αυτό το αίτημα και στη συνέχεια στέλνει μια απάντηση στον πελάτη. Αυτό το απλό μοτίβο αίτησης / απόκρισης διαμορφώνει τον τρόπο με τον οποίο το πρωτόκολλο HTTP διευκολύνει τις αλληλεπιδράσεις πελάτη / διακομιστή Web. Όπως με το HTTP, οι ανταλλαγές μηνυμάτων υπηρεσίας Web συχνά πρέπει να περιλαμβάνουν δυαδικό περιεχόμενο, όπως εικόνες, έγγραφα ή κλιπ ήχου. Αυτό το άρθρο παρουσιάζει την αποστολή και τη λήψη δυαδικού περιεχομένου υπηρεσίας Web χρησιμοποιώντας το SOAP (Simple Object Access Protocol) με το Attachments API για Java (SAAJ) 1.2.

Πριν εξερευνήσετε τις περιπλοκές της μεταφοράς δυαδικού περιεχομένου υπηρεσίας Web, αξίζει να επισημάνετε ότι μια απλή υπηρεσία Ιστού τύπου αιτήματος / απόκρισης έρχεται σε αντίθεση με τις υπηρεσίες που διαμορφώνουν την αλληλεπίδραση πελάτη / διακομιστή ως κλήσεις απομακρυσμένης διαδικασίας ή RPC. Σε ένα RPC, ένας διακομιστής εκθέτει μια διεπαφή που μοιάζει με ένα API. Με τη σειρά του, ένας πελάτης επικαλείται μια τέτοια υπηρεσία πραγματοποιώντας απομακρυσμένες κλήσεις στο API της υπηρεσίας, περνώντας τις απαιτούμενες παραμέτρους και λαμβάνοντας τις τιμές που παράγει η κλήση.

Το RPC που βασίζεται σε XML μοιάζει με τον τρόπο με τον οποίο καλείτε αντικείμενα σε ένα σύστημα αντικειμενοστρεφής (OO). Πράγματι, όταν εργάζεστε με το Java API για RPC που βασίζεται σε XML (JAX-RPC), σπάνια γνωρίζετε ότι εργάζεστε με έγγραφα XML και όχι αντικείμενα Java. Το JAX-RPC σάς επιτρέπει να θεωρείτε τις υπηρεσίες Web ως απομακρυσμένα αντικείμενα, όπως θα κάνατε με το Java RMI (Απομακρυσμένη μέθοδος επίκλησης). Ο χρόνος εκτέλεσης JAX-RPC μεταφράζει τις υψηλού επιπέδου, κλήσεις μεθόδου OO στα έγγραφα XML που αναμένονται από την απομακρυσμένη υπηρεσία Web. Ενώ οι υπηρεσίες Ιστού τύπου RPC παρέχουν συχνά ένα πιο βολικό μοντέλο προγραμματισμού, οι κλήσεις RPC πρέπει επίσης να βασίζονται σε ένα επίπεδο μηνυμάτων χαμηλότερου επιπέδου για την ανταλλαγή των μηνυμάτων XML που αποτελούν την απομακρυσμένη κλήση.

Για ορισμένες υπηρεσίες Web, είναι συχνά χρήσιμο να προγραμματίζετε απευθείας σε αυτό το επίπεδο μηνυμάτων χαμηλότερου επιπέδου. Για παράδειγμα, εάν θέλετε να επικαλεστείτε μια υπηρεσία Web που καταναλώνει ένα έγγραφο εντολής αγοράς και επιστρέφει μια απόδειξη, μπορείτε εύκολα να μοντελοποιήσετε αυτήν την ανταλλαγή εγγράφων ως μεμονωμένη ανταλλαγή μηνυμάτων αιτήματος / απάντησης. Αντί να κάνετε απομακρυσμένες μεθόδους επίκλησης, θα μπορούσατε να δημιουργήσετε μηνύματα XML, να στείλετε αυτά τα μηνύματα απευθείας σε μια υπηρεσία Web και να επεξεργαστείτε την απόκριση XML της υπηρεσίας, εάν υπάρχει. Δεδομένου ότι το SOAP καθορίζει την κοινή μορφή μηνυμάτων για μηνύματα υπηρεσίας Web, θα χρειαστεί να δημιουργήσετε μηνύματα συμβατά με SOAP και, μόλις η υπηρεσία ανταποκριθεί, αναλύστε αυτά τα μηνύματα απόκρισης SOAP σε μορφή που κατανοεί το πρόγραμμά σας.

Το SAAJ παρέχει μια βολική βιβλιοθήκη για την κατασκευή και ανάγνωση μηνυμάτων SOAP και σας επιτρέπει επίσης να στέλνετε και να λαμβάνετε μηνύματα SOAP σε όλο το δίκτυο. Το SAAJ ορίζει το χώρο ονομάτων javax.xml.soap. Οι κλάσεις που βρίσκονται σε αυτό το πακέτο αποτελούσαν αρχικά μέρος του Java API για XML Messaging (JAXM), αλλά διαχωρίστηκαν πρόσφατα στο δικό τους API. Το JAXM βασίζεται στο SAAJ για κατασκευή και χειρισμό μηνυμάτων SOAP και προσθέτει την αξιοπιστία των μηνυμάτων και άλλες λειτουργίες ειδικά για τα μηνύματα XML. Ενώ το SAAJ είναι ένα απαιτούμενο συστατικό του J2EE (Java 2 Platform, Enterprise Edition) 1.4, το JAXM δεν είναι. Αυτό το άρθρο επικεντρώνεται σε μία από τις πιο χρήσιμες πτυχές του SAAJ: τη δυνατότητα επισύναψης δυαδικού περιεχομένου σε ένα μήνυμα SOAP.

Τα οφέλη των συνημμένων

Ενώ το κέντρο σχεδίασης του SOAP επικεντρώνεται στην ενσωμάτωση εγγράφων XML σε ένα μήνυμα, η δυνατότητα συνημμένου του SOAP επεκτείνει ένα μήνυμα SOAP για να συμπεριλάβει, εκτός από το κανονικό μέρος SOAP, μηδενικά ή περισσότερα συνημμένα, όπως δείχνει η Εικόνα 1. Κάθε συνημμένο καθορίζεται από έναν τύπο MIME και μπορεί να αναλάβει οποιοδήποτε περιεχόμενο αντιπροσωπεύεται ως ροή byte.

Η δυνατότητα συνημμένου του SOAP αποδεικνύεται πιο χρήσιμη όταν ένας πελάτης επιθυμεί να μεταδώσει δυαδικά δεδομένα, όπως δεδομένα εικόνας ή ήχου, σε μια υπηρεσία Web. Χωρίς συνημμένα SOAP, η αποστολή ενός τμήματος δυαδικών δεδομένων θα αποδειχθεί πιο δύσκολη. Για παράδειγμα, ένα μήνυμα SOAP ενός πελάτη θα μπορούσε να μεταφέρει τη διεύθυνση URL του δυαδικού αρχείου. Ο πελάτης θα έπρεπε τότε να λειτουργήσει έναν διακομιστή HTTP για να επιτρέψει στην υπηρεσία Web να ανακτήσει αυτό το αρχείο. Αυτό θα αποτελούσε αδικαιολόγητη επιβάρυνση για οποιονδήποτε πελάτη υπηρεσίας Ιστού, ειδικά για πελάτες που εκτελούν συσκευές περιορισμένου πόρου, όπως ψηφιακές φωτογραφικές μηχανές ή σαρωτές. Η δυνατότητα συνημμένου του SOAP επιτρέπει σε οποιονδήποτε πελάτη υπηρεσίας Ιστού να μπορεί να μεταδίδει μηνύματα SOAP ενσωματώνοντας δυαδικά αρχεία απευθείας σε ένα μήνυμα SOAP.

Τα συνημμένα SOAP, για παράδειγμα, αποδεικνύονται βολικά όταν αλληλεπιδράτε με ιστότοπους πύλης. Σκεφτείτε ένα δίκτυο μεσιτικών ακινήτων που πρέπει να διανείμει περιγραφές και φωτογραφίες κατοικιών προς πώληση σε μια κεντρική πύλη αναζήτησης ακινήτων. Εάν η πύλη διαθέτει servlet που επιτρέπει την ανάρτηση μηνυμάτων SOAP με συνημμένα, ένα μεσιτικό γραφείο θα μπορούσε να ενημερώσει τις καταχωρίσεις του με μερικά μηνύματα SOAP, συμπεριλαμβανομένων φωτογραφιών αυτών των σπιτιών. Το σώμα μηνυμάτων SOAP μπορεί να ενσωματώσει την περιγραφή της ιδιότητας και τα συνημμένα SOAP θα μπορούσαν να μεταφέρουν τα αρχεία εικόνας. Κάτω από αυτό το σενάριο, όταν ένα servlet χειριστή πύλης λαμβάνει ένα τέτοιο μήνυμα, θα επιστρέψει ένα έγγραφο επιβεβαίωσης, το οποίο θα υποδεικνύει τη διαθεσιμότητα της ανάρτησης στην πύλη. Το σχήμα 2 απεικονίζει μια τέτοια υπηρεσία Web.

Η ανατομία του σαπουνιού με μήνυμα συνημμένων

Η σημείωση SOAP Messages with Attachments W3C (World Wide Web Consortium) (βλ. Πόρους) δεν προσθέτει νέες δυνατότητες στο SOAP. Αντίθετα, καθορίζει πώς να εκμεταλλευτείτε τους τύπους MIME σε ένα μήνυμα SOAP για να ορίσετε συνημμένα και πώς να αναφέρετε αυτά τα συνημμένα μέσα από το σώμα SOAP.

Ο τύπος MIME multipart / σχετικά ορίζει έγγραφα που αποτελούνται από πολλά σχετικά μέρη. Τα μηνύματα SOAP με συνημμένα πρέπει να ακολουθούν το multipart / σχετικά Τύπος MIME. Το παρακάτω παράδειγμα δείχνει ένα multipart / σχετικά Μήνυμα SOAP, δεσμευμένο στο πρωτόκολλο HTTP, με δύο συνημμένα:

POST / propertyListing HTTP / 1.1 Host: www.realproperties.com Τύπος περιεχομένου: Multipart / Σχετικό; όριο = MIME_boundary; type = κείμενο / xml; Μήκος περιεχομένου: NNNN --MIME_boundary Τύπος περιεχομένου: κείμενο / xml; charset = UTF-8 Content-Transfer-Encoding: 8bit Content-ID: Really Nice Homes, Inc. Προσθήκη 1234 Main St Pleasantville CA 94323 250000 --MIME_boundary Content-Type: image / jpeg Content-ID: .... JPEG DATA ..... --MIME_boundary Τύπος περιεχομένου: image / jpeg Content-ID: .... JPEG DATA ..... --MIME_boundary-- 

Το παραπάνω μήνυμα πολλαπλών μερών περιλαμβάνει μια σειρά κεφαλίδων MIME και σχετικά δεδομένα. Στη ρίζα του εγγράφου βρίσκεται το σώμα του σαπουνιού. Επειδή το σώμα SOAP περιέχει μόνο δεδομένα XML, ο τύπος MIME ολόκληρου του μηνύματος είναι κείμενο / xml. Μετά το φάκελο SOAP υπάρχουν δύο συνημμένα, το καθένα αντιστοιχεί σε ένα αρχείο εικόνας που αποστέλλεται μαζί με το μήνυμα.

Ένα αναγνωριστικό περιεχομένου προσδιορίζει κάθε συνημμένο. Η Σημείωση W3C επιτρέπει είτε ένα αναγνωριστικό περιεχομένου είτε μια τοποθεσία περιεχομένου να αναφέρει τα συνημμένα, αλλά δίνει προτεραιότητα στα προηγούμενα. Τέτοια αναγνωριστικά περιεχομένου λειτουργούν ως αναφορές Uniform Resource Identifier (URI) σε συνημμένα. οι κανόνες κωδικοποίησης SOAP 1.1 καθορίζουν τον τρόπο αναφοράς ενός πόρου σε ένα μήνυμα SOAP μέσω ενός URI που μπορεί να αναφέρει οποιοδήποτε περιεχόμενο, όχι μόνο XML (βλ. Ενότητα 5 του SOAP 1.1 στους πόρους). Ένας επεξεργαστής SOAP επιλύει αυτές τις αναφορές URI καθώς επεξεργάζεται το μήνυμα. Με βάση το παραπάνω παράδειγμα, ο επεξεργαστής SOAP συσχετίζει το στοιχείο μπροστινή εικόνα με την ενότητα δεδομένων με το Content ID [email protected] στο μήνυμα SOAP.

Δημιουργήστε και στείλτε ένα μήνυμα SOAP με συνημμένα

Το SAAJ σάς επιτρέπει να δημιουργείτε και να επεξεργάζεστε οποιοδήποτε μέρος ενός μηνύματος SOAP, συμπεριλαμβανομένων των συνημμένων. Το μεγαλύτερο μέρος του SAAJ βασίζεται σε αφηρημένες τάξεις και διεπαφές έτσι ώστε κάθε πάροχος να μπορεί να εφαρμόσει το SAAJ στα δικά του προϊόντα. Η εφαρμογή αναφοράς της Sun Microsystems συνοδεύεται από το Java Web Services Developer Pack (JWSDP).

Δεδομένου ότι τα μηνύματα SOAP αντιπροσωπεύουν αλλά μια ειδική μορφή εγγράφων XML, το JAAS βασίζεται στο API Document Object Model (DOM) για επεξεργασία XML. Τα περισσότερα στοιχεία μηνυμάτων SOAP κατεβαίνουν από το javax.xml.soap.Node διεπαφή, η οποία, με τη σειρά της, είναι org.w3c.dom.Node υποδιαίρεση τάξεως. Υποκατηγορίες SAAJ Κόμβος για να προσθέσετε συγκεκριμένες κατασκευές SOAP. Για παράδειγμα, ένα ειδικό Κόμβος, ΣΑΠΟΥΝΙ, αντιπροσωπεύει ένα στοιχείο μηνύματος SOAP.

Ένα άμεσο αποτέλεσμα της εξάρτησης της SAAJ από διεπαφές και αφηρημένες τάξεις είναι ότι επιτελείτε τις περισσότερες εργασίες που σχετίζονται με το SOAP μέσω εργοστασιακών μεθόδων. Για να συνδέσετε την εφαρμογή σας με το API SAAJ, δημιουργείτε πρώτα ένα SOAP Σύνδεση από ένα SOAPConnectionFactory. Για τη δημιουργία και επεξεργασία μηνυμάτων SOAP, μπορείτε επίσης να αρχικοποιήσετε ένα Εργοστάσιο μηνυμάτων και ένα Σαπούνι. Εργοστάσιο μηνυμάτων σας επιτρέπει να δημιουργήσετε μηνύματα SOAP και Σαπούνι παρέχει τις μεθόδους για τη δημιουργία μεμονωμένων τμημάτων ενός μηνύματος SOAP:

SOAPConnectionFactory spConFactory = SOAPConnectionFactory.newInstance (); SOAPConnection con = spConFactory.createConnection (); SOAPFactory soapFactory = SOAPFactory.newInstance (); 

Με αυτά τα εργαλεία στη θέση τους, μπορείτε να δημιουργήσετε ένα μήνυμα SOAP που θα χρησιμοποιούσε ένας πελάτης από ένα μεσιτικό γραφείο για να στείλει μια ενημέρωση καταχώρισης σε έναν ιστότοπο πύλης.

Το SAAJ προσφέρει διάφορους τρόπους για να δημιουργήσετε ένα νέο μήνυμα SOAP. Το παρακάτω παράδειγμα δείχνει την απλούστερη μέθοδο που δημιουργεί ένα κενό μήνυμα SOAP με φάκελο και κεφαλίδα και σώμα σε αυτόν τον φάκελο. Εφόσον δεν χρειάζεστε μια κεφαλίδα SOAP σε αυτό το μήνυμα, μπορείτε να καταργήσετε αυτό το στοιχείο από το μήνυμα:

SOAPMessage message = factory.createMessage (); SOAPHeader header = message.getSOAPHeader (); header.detachNode (); 

Η προσθήκη της δομής XML στο σώμα μηνυμάτων αποδεικνύεται απλή:

SOAPBody body = message.getSOAPBody (); Name listElementName = soapFactory.createName ("propertyListing", "realProperty", "//schemas.realhouses.com/listingSubmission"); SOAPBodyElement listingElement = body.addBodyElement (listingElementName); Όνομα attname = soapFactory.createName ("id"); listingElement.addAttribute (όνομα χρήστη, "property_1234"); SOAPElement listingAgency = listingElement.addChildElement ("listingAgency"); listingAgency.addTextNode ("Really Nice Homes, Inc"); SOAPElement listingType = listingElement.addChildElement ("listingType"); listingType.addTextNode ("προσθήκη"); SOAPElement propertyAddress = listingElement.addChildElement ("propertyAddress"); SOAPElement street = propertyAddress.addChildElement ("δρόμος"); street.addTextNode ("1234 Main St"); SOAPElement city = propertyAddress.addChildElement ("πόλη"); city.addTextNode ("Pleasantville"); SOAPElement state = propertyAddress.addChildElement ("κατάσταση"); state.addTextNode ("CA"); SOAPElement zip = propertyAddress.addChildElement ("zip"); zip.addTextNode ("94521"); SOAPElement listPrice = listingElement.addChildElement ("listPrice"); listPrice.addTextNode ("25000"); 

Σημειώστε ότι προσθέτετε το μοναδικό αναγνωριστικό της ιδιότητας ως χαρακτηριστικό στο Ακίνητα στοιχείο. Επιπλέον, πληροίτε τα κριτήρια Ακίνητα στοιχείο με ένα QNameή όνομα που γνωρίζει το χώρο.

Μπορείτε να προσθέσετε συνημμένα στο μήνυμα SOAP με διάφορους τρόπους. Σε αυτό το παράδειγμα, δημιουργείτε πρώτα στοιχεία για να υποδηλώσετε τις εμπρόσθιες και εσωτερικές εικόνες της ιδιότητας. Κάθε ένα έχει href χαρακτηριστικό που προσδιορίζει το αναγνωριστικό περιεχομένου του συνημμένου:

String frontImageID = "[email protected]"; SOAPElement frontImRef = listingElement.addChildElement ("frontImage"); Όνομα hrefAttName = soapFactory.createName ("href"); frontImRef.addAttribute (hrefAttName, frontImageID); String interiorID = "[email protected]"; SOAPElement interiorImRef = listingElement.addChildElement ("interiorImage"); interiorImRef.addAttribute (hrefAttName, interiorID); 

Για να επισυνάψετε εύκολα τα απαιτούμενα αρχεία εικόνας στο μήνυμα, χρησιμοποιήστε το a javax.activation.DataHandler αντικείμενο από το JavaBeans Activation Framework. DataHandler μπορεί να ανιχνεύσει αυτόματα τον τύπο δεδομένων που του μεταβιβάστηκε και, ως εκ τούτου, μπορεί αυτόματα να εκχωρήσει τον κατάλληλο τύπο περιεχομένου MIME στο συνημμένο:

URL url = νέο URL ("file: ///export/files/pic1.jpg"); DataHandler dataHandler = νέο DataHandler (url); AttachmentPart att = message.createAttachmentPart (dataHandler); att.setContentId (frontImageID); message.addAttachmentPart (att); 

Εναλλακτικά, μπορεί να μπορείτε να περάσετε ένα Αντικείμενο, μαζί με τον σωστό τύπο MIME, σε createAttachmentPart (). Αυτή η μέθοδος μοιάζει με την πρώτη. Εσωτερικά, η εφαρμογή SAAJ πιθανότατα θα αναζητήσει ένα DataContentHandler για να χειριστείτε τον καθορισμένο τύπο MIME. Εάν δεν μπορεί να βρει έναν κατάλληλο χειριστή, createAttachmentPart () θα ρίξει ένα IlegalArgumentException:

URL url2 = νέο URL ("file: ///export/files/pic2.jpg"); Image im = Toolkit.getDefaultToolkit (). CreateImage (url2); AttachmentPart att2 = message.createAttachmentPart (im, "image / jpeg"); att2.setContentId (interiorID); message.addAttachmentPart (att2);