Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

(Posted on behalf of Gary Lamperillo)

Seam works well with the JSF lifecycle allowing updates to be handled on a JSF DataTable using a combination of the Seam DataModel and DataModelSelection annotations. When using Seam with Web Services there are no such easy entry points. In place of a DataSelection, a look up of the updated by ID should be performed. Perhaps, in some future release We may get something from Seam, but for now this is what works. I have used an Outjected List which I provide to a JBoss-WS JAX-WS Web Client, and then return the detached object back to a Stateful Session bean. At this point, I lookup the ID of the detached object in the Stateful Session bean Outjected list, and call setters to update this entry.

I follow the seam model as in the Reference manual of having a Stateless Web Service to front the Stateful Bean:

I use the Component.getInstance() to lookup the Stateful Session Bean component and the Outjected list.

To keep the conversation maintained on the client side and the server side, we need SOAPHandlers. Seam provides a server side handler, which can be installed by placing it in the meta-inf of the EJB project. I have created the client side SOAPHandler by modifying the server side SOAPHandler, so as not to call any Seam Lifecycle methods. Here is a flow diagram:

The client side handler looks like this:

public class SOAPRequestHandler implements SOAPHandler
{

  Private String conversationId;
  …

public boolean handleMessage(MessageContext msgContext)
   {
      Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
      if (outbound == null)
         throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);

return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
   } 

   public boolean handleInbound(MessageContext messageContext)
   {
	   
	  
	   
      try
      {
HttpServletRequest request = (HttpServletRequest)     messageContext.get(MessageContext.SERVLET_REQUEST);      
         conversationId = extractConversationId(messageContext);
         System.out.println("handleInbound... cid = " + conversationId);
         return true;
      }
      catch (SOAPException ex)
      {
         System.err.println("Error handling inbound SOAP request" + ex);
         return false;
      }
   }
 …


}

I use the SoapHandler as a location to store the conversationId.

A Web Service Client can mostly be created from tools, one tool which we found useful has an eclipse plugin, this tool is called soapUI (http://www.soapui.org/). This tool can create clients for JBoss-WS, Axis , JAX-RPC, Oracle and .NET. We will used only the JBoss-WS JAX-WS. The Web Service client must also add the soaphandlers, see the example

void GetHotels(String[] args) {
     		try {
       
HotelService port = new      HotelService_Service().getHotelServicePort();
            BindingProvider bp = (BindingProvider)port;
      
       
       	ArrayList l = new ArrayList();
       	l.add(new com.sony.spe.ws.SOAPRequestHandler());
      	bp.getBinding().setHandlerChain(l);
       
       
       
      port.HotelSearch(“marriot”);

	…
}

In this section we will demonstrate the use of the SoapUI Eclipse plugin. In set up of this, you will first need to create a Java project in eclipse. On the right click of the Java Project a new subsection called SoapUI is available, select “add SoapUI nature”. You can now change to the SoapUI perspective and follow these steps.

1.Generate code based on a wsdl on a server. Select JBossWS JAX-WS artifacts.

2. Select the wsdl which is available on the server, the package which you would like the classes to be created in and the source folder.

3.Select the Tools button and setup the tool and path information for the JBossWS Tools which are available in the bin directory of the JBoss AS 4.3.

4. Clicking the generate button after the proper setup should return a successful message and all Web Service client artifacts will now be available for use on the Seam or Java perspective.

As we mentioned, we use the detached object’s id to find the object on the Stateful Session Bean’s outjected component, here is an example on how to do this:

 public void updateHotel(Hotel hotel)
   { 	     
	   int count = hotels.size();
       for(int i = 0; i<count; i++)
       {
    	     Hotel h = (Hotel)hotels.get(i);
    	     
    	     if(h.getId().equals(hotel.getId()))
    	     {
    	       h.setName(hotel.getName());
    		   hotel = h;
    	       break;
    	      }
    	   
       }
4 comments:
 
12. Jan 2009, 00:01 America/New_York | Link

Following your instruction i get No active event context exception, i used the modified SOAPHandler and added it as described, should i do anything else ? because i'm sure that my web services work ( i've modified the test javascript in seambay and tested my web services, it worked fine )

Thank you, Nguyen Duy Ninh

 
16. Mar 2009, 07:14 America/New_York | Link

Make sure the soaphandler is installed properly. I would debug it, print out the conversation ids from the soaphandler.

 
09. Dec 2009, 19:16 America/New_York | Link

When I try and set the converstionId on subseqent requests my SOAPHeader is always null, as such the value never gets set.

SOAPMessageContext smc = (SOAPMessageContext) messageContext;	           	       
SOAPHeader header = smc.getMessage().getSOAPHeader();
	            
if (header != null)
{
     SOAPElement element = header.addChildElement(CIDQN);
     element.addTextNode(conversationId);
     smc.getMessage().saveChanges();               
}  

Doe's anyone have any ideas why this could be?

Thanks

Craig

 
07. Apr 2010, 12:52 America/New_York | Link
Miquel

To be able to mantain login between web service calls you should add to proxy:

_*BindingProvider bp = (BindingProvider)port1; bp.getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,true);*_