Use Cases for Petals-SE-JSR181

This document is a complement to the documentation of the Petals SE-JSR181 component.
It assumes that you already know how to generate a JSR181 SU using PetalsStudio: most code examples detailed here are embedded in the JSR181 SU main class, pointed as <jsr181:class> in the jbi.xml of the SU.

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.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.