This document is a complement to the documentation of the Petals SE-JSR181 component. When building a JSR181 Service Unit using Maven, the JBIContextManager is provided by the dependency petals-se-jsr181-library. This dependency must be defined using the scope provided as it is provided by the container. |
Implementing a web method that deals with complex types and attachments
Text File Extraction
This example receives a text file as an attachment and returns its content to the client.
Attachment's style is MTOM.
package com.ebmwebsourcing; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.activation.DataHandler; import javax.jws.WebMethod; import javax.jws.WebResult; import javax.jws.WebService; import javax.xml.ws.BindingType; import javax.xml.ws.soap.SOAPBinding; /** * Here is a sample JAX-WS implementation. */ @WebService( serviceName="Test", targetNamespace="http://ebmwebsourcing.com", portName="TestPort" ) @BindingType(SOAPBinding.SOAP11HTTP_MTOM_BINDING) public class Test { /** * Extracts the content from the received attachment. */ @WebMethod( operationName="extractContent" ) @WebResult( name="returnMessage" ) public String extractContent( DataHandler textDocument ) { String result = "An error occurred."; ByteArrayOutputStream os = new ByteArrayOutputStream(); try { copyStream( textDocument.getInputStream(), os ); result = os.toString( "UTF-8" ); } catch (IOException e) { e.printStackTrace(); } return result; } /** * Copies the content from in into os. * <p> * Neither <i>in</i> nor <i>os</i> are closed by this method.<br /> * They must be explicitly closed after this method is called. * </p> * * @param in * @param os * @throws IOException */ public static void copyStream( InputStream in, OutputStream os ) throws IOException { byte[] buf = new byte[ 1024 ]; int len; while((len = in.read( buf )) > 0) { os.write( buf, 0, len ); } } }
JAX-WS annotations
This example is an upload method: it receives path + file name information (where to store the file) as a parameter, and a file to upload (as a binary attachment). In this example, we retrieve attachments directly from the Petals exchange.
@WebMethod( operationName="upload" ) public String upload(@WebParam( name="destination" ) UploadDestination dest) { // Get the JBI context JBIContext jbiContext = JBIContextManager.getJBIContext(); Exchange exchange = jbiContext.getExchange(); try { Set<DataHandler> atts = exchange.getInMessageAttachments(); int n = 0; for(DataHandler att : atts) { if(n == 1) { // Ignore 1st attachment (bug workaround... may be useless with latest release ?) FileOutputStream out = new FileOutputStream(dest.getPath() + File.separator + dest.getName()); InputStream in = att.getInputStream(); byte buf[] = new byte[256]; while(in.read(buf) >= 0) { out.write(buf); } out.close(); } n++; } } catch (Exception e) { Logger.getLogger( getClass().getName()).severe("Upload error: " + e.getMessage()); } return "upload destination=" + dest; }
Class for complex type parameter
This class is a simple JavaBean (POJO with getter/setter methods for each field: here, fields are "path" and "name", as the class represents an "upload destination" = a file).
package org.ow2.petals.usecase.jsr181; public class UploadDestination { String name_ = "/tmp"; String path_ = "petals-attachment"; public String getName() { return name_; } public void setName(String name) { this.name_ = name; } public String getPath() { return path_; } public void setPath(String path) { this.path_ = path; } public String toString() { return (path_ == null ? "" : path_) + "/" + name_; } }
Invoking a Petals service
This class illustrates how a JSR-181 implementation can invoke a Petals service.
The invoked service is here a mailing service.
package org.ow2.sample; import java.util.logging.Logger; import javax.jbi.messaging.MessagingException; import javax.jws.Oneway; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; import javax.xml.namespace.QName; import org.ow2.petals.component.framework.api.Message.MEPConstants; import org.ow2.petals.component.framework.api.exception.PEtALSCDKException; import org.ow2.petals.component.framework.api.message.Exchange; import org.ow2.petals.jsr181.JBIContext; import org.ow2.petals.jsr181.JBIContextManager; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.ebmwebsourcing.easycommons.xml.DocumentBuilders; /** * Here is a sample JAX-WS implementation. */ @WebService( serviceName="MailProxyService", targetNamespace="http://sample.ow2.org", portName="MailProxyServicePort" ) public class MailProxyService { /* (non-Javadoc) * @see JaxWSInterface#HelloWorld() */ @WebMethod( operationName="helloWorld" ) @WebResult( name="returnMessage" ) public String helloWorld() { return "Hello World!"; } /* * Propagates a message as an email service invocation. */ @WebMethod( operationName="listenToTheWorld" ) @Oneway public void propagateMessage( @WebParam( name="message" ) String message ) { // We here illustrate a method that does not return anything. // This method uses a Petals extension to invoke other services in the bus. // Get the JBI context JBIContext jbiContext = JBIContextManager.getJBIContext(); // Create the mail content StringBuilder mailContent = new StringBuilder(); mailContent.append( "Propagating the received message...\n" ).append( message ); // Create a XML document... final String MAIL_NS = "http://petals.ow2.org/components/mail/version-3"; Document mailDocument = DocumentBuilders.newDocument(); final Element mailElement = mailDocument.createElementNS( MAIL_NS, "mail" ); mailDocument.appendChild( mailElement ); final Element bodyElement = mailDocument.createElementNS( MAIL_NS, "body" ); mailElement.appendChild( bodyElement ); bodyElement.setTextContent( mailContent.toString()); // ... and send it to a mailing service. try { final Exchange mailExchange = jbiContext.getMessageSender().createExchange( MEPConstants.IN_ONLY_PATTERN ); mailExchange.setInterfaceName( new QName( "http://petals.ow2.org/components/mail/version-3", "Mail" )); mailExchange.setService( new QName( "http://petals.ow2.org/components/mail/version-3", "ReportMailService" )); mailExchange.setOperation(new QName("http://petals.ow2.org/components/mail/version-3", "SendMail")); mailExchange.setInMessageContent( mailDocument ); // Synchronous invocation jbiContext.getMessageSender().send( mailExchange ); } catch( MessagingException e ) { Logger.getLogger( getClass().getName()).severe( "Failed to send a message to the Petals Mail component. Messaging error." ); } catch( PEtALSCDKException e ) { Logger.getLogger( getClass().getName()).severe( "Failed to send a message to the Petals Mail component. Petals CDK error." ); } } }
Making the JSR-181 more configurable
Your JSR-181 implementation may need to access extra files you put in your service unit.
You may also want to add parameters or properties to your service unit.
Additional properties should be put in a distinct file, at the root of the service unit.
These resources can be accessed by using the class loader.
Here is an example showing how to access a properties file located in the service unit.
package com.ebmwebsourcing; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Properties; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; /** * Here is a sample JAX-WS implementation. */ @WebService( serviceName="Test2", targetNamespace="http://ebmwebsourcing.com", portName="TestPort2" ) public class Test2 { /** * @param key * @return */ @WebMethod( operationName="getProperty" ) @WebResult( name="returnProperty" ) public String getProperty( @WebParam( name="key" ) String key ) { String result = "Oops!"; URL url = getClass().getResource( "/my-properties.properties" ); Properties properties = new Properties(); try { InputStream is = url.openStream(); properties.load( is ); result = properties.getProperty(key, "Invalid key"); } catch (IOException e) { e.printStackTrace(); } return result; } }
Notice that in the studio, the resources must be added under the src/main/jbi directory.
This way, they will be put at the root of the service unit.