Seam and SOA

I am in Atlanta for our internal JBoss ESB / SOA training this week. Burr Sutter and his team are doing a great job conveying our SOA vision -- to mesh and reuse services you already built in your "single silo" applications (e.g., a web store and a warehouse management app can share an "order" object when the user confirms an order. Each application then process and save the order in their own ways.).

I have been thinking how Seam fits into this picture. With the support for web services in Seam 2.0, it is actually quite easy to fit a Seam application into a SOA environment. In this post, I'd like to discuss some work I did with the seambay example (a spoof auction site) to make it share its listings with other services, and receive listings from other services.

@Out

To make the seambay application share its auction listings with other services in the SOA environment, we need to serialize the Auction object and push it to the ESB, while it is being saved into the database by the Seam application. The least intrusive way to do this is to use an EJB3 interceptor to "steal" the Auction object when the confirm() method is called. This way, we do not need to make any change to the Seam application code.

JAVA:
  1. public class AuctionInterceptor {
  2.  
  3.   @AroundInvoke
  4.   public Object sendAuctionToESB (InvocationContext ctx) throws Exception {
  5.  
  6.     System.out.println("*** Entering AuctionInterceptor");
  7.  
  8.     Object target = ctx.getTarget ();
  9.     if (target instanceof AuctionAction) {
  10.       if (ctx.getMethod().getName().equals("confirm")) {
  11.         System.out.println("We will send the following Auction object to ESB");
  12.         Auction auction = ((AuctionAction) target).getAuction ();
  13.         // Send the following XML string to JMS
  14.         formatMessage(auction);
  15.       }
  16.     }
  17.  
  18.     try {
  19.       return ctx.proceed();
  20.     } finally {
  21.        System.out.println("*** Exiting AuctionInterceptor");
  22.     }
  23.   }
  24.   ... ...
  25. }

When the user enters a new auction listing on the site, the server console prints the following message.

Picture 18.png

@In

To make the Seam application as a SOA service end-point requires external applications to invoke its business logic through web services. The challenge here is that most business logic in Seam are managed in "conversations", which holds finer grained application state than Http sessions. How do you keep the conversation state across multiple SOAP calls? Well, here is where the Seam Web Service comes into play.

To expose business logic methods in Seam components as Web Service methods, you need to write a facade SLSB to wrap around the methods you want to expose. You can use the Seam.getComponent() method to get any Seam component by its name and then proceed to invoke any method on the component.

JAVA:
  1. @Stateless
  2. @WebService(name = "AuctionService", serviceName = "AuctionService")
  3. public class AuctionService implements AuctionServiceRemote
  4. {
  5.    @WebMethod
  6.    public boolean login(String username, String password)
  7.    {
  8.       Identity.instance().setUsername(username);
  9.       Identity.instance().setPassword(password);
  10.       Identity.instance().login();
  11.       return Identity.instance().isLoggedIn();
  12.    }
  13.  
  14.    @WebMethod
  15.    public void createAuction(String title, String description, int categoryId)
  16.    {
  17.       AuctionActionInt action = getAuctionAction();
  18.       action.createAuction();
  19.       action.setDetails(title, description, categoryId);
  20.    }
  21.  
  22.    @WebMethod
  23.    public Auction getNewAuctionDetails()
  24.    {
  25.       return getAuctionAction().getAuction();
  26.    }
  27.  
  28.     @WebMethod
  29.    public void setAuctionPrice(double price)
  30.    {
  31.       getAuctionAction().getAuction().setPrice(price);
  32.    }
  33.  
  34.    @WebMethod
  35.    public void confirmAuction()
  36.    {
  37.       getAuctionAction().confirm();
  38.    }
  39.  
  40.    private AuctionActionInt getAuctionAction()
  41.    {
  42.       // Get seam component named "auctionAction" from context
  43.       return (AuctionActionInt) Component.getInstance("auctionAction", true);
  44.    }
  45.    ... ...
  46. }

Notice that the createAuction(), setAuctionDuration(), setAuctionPrice() and confirmAuction() methods all need to happen in the same conversation so that they can access the same "auctionAction" component. But we do not explicitly pass the conversation id to the web service calls. Instead, when the createAuction() method returns, it inserts a conversation id in the SOAP header, and expect the client to use the same conversation id in the header until the caller reaches confirmAuction(), which ends the conversation. The SOAP request inside a conversation looks like the following:

XML:
  1. <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  2.                            xmlns:seam="http://seambay.example.seam.jboss.org/">
  3.    <soapenv:Header>
  4.       <seam:conversationId>2</seam:conversationId>
  5.    </soapenv:Header>
  6.    <soapenv:Body>
  7.       <seam:setAuctionPrice>
  8.          <arg0>20</arg0>
  9.       </seam:setAuctionPrice>
  10.    </soapenv:Body>
  11. </soapenv:Envelope>

As a proof of concept to demonstrate that Seam web service is well supported by existing SOAP tools, I build a SoapUI script to demonstrate how to add an auction to the Seam app via web services. Notice the "transfer" elements in the script. They are used to maintain the conversation id header across SOAP requests in a conversation.

Picture 17.png

Finally, I'd like to make the SOA version of the seambay example available for download. You can find the ready built EAR file in the dist directory, as well as the SoapUI script in the root directory.

12 Responses to “Seam and SOA”

  1. Siarhei Says:

    Any plans on doing the training in Europe?

  2. Michael Yuan Says:

    Yes, actually we are trying to identify early adopters for JBoss ESB / SOA — we will be able to provide *free* training and consulting services to those clients. If you want to be part of the program, please let me know and I will ask our SOA guys to contact you.

    cheers
    Michael

  3. Rob Says:

    Hi, have your book and I really like seam and I want to use seam for a production app. I noticed that the support page has not been updated this year and there are a number of outstanding issues in jira going back as much as six months. Can you give me an update on the status of the project? Thanks Rob

  4. Michael Yuan Says:

    Rob,

    Actually, Red Hat does provide official support for Seam 1.2.1 through the JBoss Enterprise Application Platform subscription.

    As for Seam itself, yes, a lot of work has been done in the past weeks. We are addressing JIRA issues listed under the Seam 2.0.0 CR1 module right now. If there are “old” issues you’d like to escalate, you feel free to raise them on the forum and we will go over them. Thanks.

    cheers
    Michael

  5. Michael Yuan Says:

    Can you possibly use Seam 2.0 (in CVS)? I believe this issue is fixed in Seam 2.0. It is hard for us to go back and release updates for the Seam 1.2.1 branch (we will probably have to if a support customer demands it …)

    There are a few more configuration changes you need to make in order to run Seam 2.0. Please see the migration readme file in the Seam 2.0 root directory for more. Thanks.

  6. Rob Says:

    Thanks for your reply, I will get 2.0, I hope to see the wiki more up to date, I went through this kind of thing with jboss portal and it just seemed dead even though a lot of work was being put into it. Rob

  7. Alex Says:

    I’m quite interested in Europe training topic. What is the most efficient way to register?

  8. Steve Says:

    I’m interested in the ESB “early adopter” opportunity. Let me know how to get in touch.

  9. Shashank Says:

    I would be interested in the JBoss “early adopter” opportunity. Is Mark the right person to contact?What email can one reach you at?

  10. David Says:

    Hi Michael,

    I am actually planning to use Seam 2.0 and its SOA features in a future-product and I’m very interested in training and the JBoss “early adopter” opportunity.
    Which is person I can contact about this?

    David

  11. Jim Solderitsch Says:

    I tried to run the example from the SOAP UI tool and I get the error:

    Fri Nov 30 17:33:23 EST 2007:WARN:Failed to prettyPrint xml [JBossWeb/2.0.1.GA - Error report HTTP Status 404 - /AuctionServiceService/AuctionServicetype Status reportmessage /AuctionServiceService/AuctionServicedescription The requested resource (/AuctionServiceService/AuctionService) is not available.JBossWeb/2.0.1.GA]: org.apache.xmlbeans.XmlException: error: does not close tag .
    Fri Nov 30 17:33:23 EST 2007:WARN:Failed to prettyPrint xml [JBossWeb/2.0.1.GA - Error report HTTP Status 404 - /AuctionServiceService/AuctionServicetype Status reportmessage /AuctionServiceService/AuctionServicedescription The requested resource (/AuctionServiceService/AuctionService) is not available.JBossWeb/2.0.1.GA]: org.apache.xmlbeans.XmlException: error: does not close tag .

    Any ideas? I did an ant deploy and it seemed to work — no errors.

    I am using JBoss 4.2.2 and the latest Seam (2.0.0GA)

    Jim

  12. Ulrike Says:

    @Jim: Replace the endpoint with ‘/jboss-seam-bay-jboss-seam-bay/AuctionService’
    and it will work.
    JBoss 4.2.2 shows the registered service endpoints on http://localhost:8080/jbossws/services

Leave a Reply