Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / Apache

Pirates and Session Beans - There is a Relation

4.00/5 (7 votes)
19 Jul 2008CPOL4 min read 3  
An article about pirates and session beans - there is a relation

Web Service Domain Requirement

My friend Matt Raible compared an AppFuse service delegate or manager class to the Session Facade. This had me thinking about this a lot this weekend. I was using Stateless SessionBean Web Services that BMW North America was accessing to prepare reports for their customer satisfaction survey data. This data was important to them because it provided a country-wide dealership dashboard for performance metrics. When I was preparing these Web services, I had a template J2EE project that I put together that would access Oracle stored procedures using pure JDBC callable statements but isolating the client calls using a JBoss container and these hosted session beans.

I always felt that these services were too simple because I copied this project everytime I created a new Web service. I had a thought in the back of my mind that maybe I would see performance problems and all the flack I'd heard about EJB's would be my ruin. While I do think that using EJBs for persistence prior to version 3.0 was overkill, Session EJB's have their place. I had success with using Session beans for my Web services.

The design was quite simple. The Session bean would host the Web service methods. I created a request and response object e.g. DetailReportArgObj and DetailReportReplyObj.java respectively. These simple Java beans were used to first process the Web service report request arguments ultimately to the Oracle stored procedure and then the reply object would return the data that modeled a report row.

Here's an example of the request and response value objects:

Java
package com.isky.detail;

/** A custom data object class that specifies a custom serializer
 *
 *  @jboss-net.xml-schema urn="DetailReport:DetailReportArgObj"
 */
public class DetailReportArgObj implements java.io.Serializable
{
       private String _endDate;
       private String _programId;
       private String _orgId;
       private String _orgLevel;

   public DetailReportArgObj()
   {
   }

   public DetailReportArgObj(String _reportType,
               String _endDate, String _orgId, String _programId,
            String _orgLevel )
   {
          this._endDate = _endDate;
          this._programId = _programId;
          this._orgId = _orgId;
          this._orgLevel = _orgLevel;
   }

    /**
     * @return Returns the _programId.
     */
    public String get_programId() {
        return _programId;
    }

    /**
     * @param date The _programId to set.
     */
    public void set_programId(String id) {
        _programId = id;
    }

    /**
     * @return Returns the _endDate.
     */
    public String get_endDate() {
        return _endDate;
    }

    /**
     * @param date The _endDate to set.
     */
    public void set_endDate(String date) {
        _endDate = date;
    }

    /**
         * @return Returns the _orgId.
     */
    public String get_orgId() {
        return _orgId;
    }

    /**
     * @param id The _orgId to set.
     */
    public void set_orgId(String id) {
        _orgId = id;
    }

    /**
     * @return Returns the _orgLevel.
     */
    public String get_orgLevel() {
        return _orgLevel;
    }

        /**
     * @param level The _orgLevel to set.
     */
    public void set_orgLevel(String level) {
        _orgLevel = level;
    }
}

package com.isky.detail;

 /** A custom data object class that needs to specify a custom serializer
  *
  *  @jboss-net.xml-schema urn="DetailReport:DetailReportReplyObj"
  */
 public class DetailReportReplyObj implements java.io.Serializable
 {
   private String _lineNo;
   private String _lineText;
   private String _labelText;
   private String _janScore;
   private String _febScore;
   private String _marScore;
...
   private String _ytdScore;

   public DetailReportReplyObj()
   {
   }

  /**
   * @return Returns the _aprScore.
   */
  public String get_aprScore() {
    return _aprScore;
  }

  /**
   * @param score The _aprScore to set.
   */
  public void set_aprScore(String score) {
    _aprScore = score;
  }

  ...

  /**
   * @return Returns the _labelText.
   */
  public String get_labelText() {
    return _labelText;
  }

  /**
   * @param text The _labelText to set.
   */
  public void set_labelText(String text) {
    _labelText = text;
  }

  ...

  // your basic Java Bean
}

The beauty in these Web service projects was the ability to specify the requirements back to the Oracle development staff and keep the Web service interface virtually the same between various Web services. I was also able to keep the Web Service Definition Language (WSDL) (pronounced wizz-duhl) similar between services and was able to copy the file and basically refactor the names of things between services. I didn't truly write these projects from scratch. I pirated them in an entirely legal way from the open source community.

Here's an example WSDL file that defines the Web Service that I hosted:

XML
<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitions
    targetNamespace="http://localhost:8080/jboss-net/services/DetailReport"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:apachesoap="http://xml.apache.org/xml-soap"
   xmlns:impl="http://localhost:8080/jboss-net/services/DetailReport"
   xmlns:intf="http://localhost:8080/jboss-net/services/DetailReport"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:tns1="http://localhost/DetailReportBean"
   xmlns:tns2="http://net.jboss.org/jmx"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">

   <wsdl:types>
      <schema targetNamespace="http://localhost/DetailReportBean"
              xmlns="http://www.w3.org/2001/XMLSchema">
         <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
         <complexType name="DetailReportArgObj">
            <sequence>
               <element name="_endDate" nillable="true" type="xsd:string"/>
               <element name="_orgId" nillable="true" type="xsd:string"/>
               <element name="_orgLevel" nillable="true" type="xsd:string"/>
               <element name="_programId" nillable="true" type="xsd:string"/>
            </sequence>
         </complexType>
         <complexType name="DetailReportReplyObj">
            <sequence>
               <element name="_labelText" nillable="true" type="xsd:string"/>
               <element name="_lineNo" nillable="true" type="xsd:string"/>
               <element name="_lineText" nillable="true" type="xsd:string"/>
               <element name="_qualifier" nillable="true" type="xsd:string"/>
               <element name="_janScore" nillable="true" type="xsd:string"/>
               <element name="_febScore" nillable="true" type="xsd:string"/>
               <element name="_marScore" nillable="true" type="xsd:string"/>
               <element name="_aprScore" nillable="true" type="xsd:string"/>
               <element name="_mayScore" nillable="true" type="xsd:string"/>
               <element name="_junScore" nillable="true" type="xsd:string"/>
               <element name="_julScore" nillable="true" type="xsd:string"/>
               <element name="_augScore" nillable="true" type="xsd:string"/>
               <element name="_sepScore" nillable="true" type="xsd:string"/>
               <element name="_octScore" nillable="true" type="xsd:string"/>
               <element name="_novScore" nillable="true" type="xsd:string"/>
               <element name="_decScore" nillable="true" type="xsd:string"/>
               <element name="_ytdScore" nillable="true" type="xsd:string"/>
            </sequence>
         </complexType>
      </schema>

      <schema targetNamespace="http://localhost:8080/jboss-net/services/DetailReport"
                  xmlns="http://www.w3.org/2001/XMLSchema">
         <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
         <complexType name="ArrayOf_xsd_anyType">
            <complexContent>
               <restriction base="soapenc:Array">
                  <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:anyType[]"/>
               </restriction>
            </complexContent>
         </complexType>
      </schema>
   </wsdl:types>
   <wsdl:message name="DetailReportRequest">
      <wsdl:part name="in0" type="xsd:anyType"/>
   </wsdl:message>
   <wsdl:message name="DetailReportResponse">
      <wsdl:part name="DetailReportReturn" type="impl:ArrayOf_xsd_anyType"/>
   </wsdl:message>
   <wsdl:portType name="DetailReport">
      <wsdl:operation name="getReport" parameterOrder="in0">
         <wsdl:input message="impl:DetailReportRequest" name="DetailReportRequest"/>
         <wsdl:output message="impl:DetailReportResponse" name="DetailReportResponse"/>
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="DetailReportSoapBinding" type="impl:DetailReport">
      <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name="getReport">
         <wsdlsoap:operation soapAction="DetailReport"/>
         <wsdl:input name="DetailReportRequest">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                namespace="http://localhost:8080/jboss-net/services/DetailReport"
                use="encoded"/>
         </wsdl:input>
         <wsdl:output name="DetailReportResponse">
            <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                namespace="http://localhost:8080/jboss-net/services/DetailReport"
                use="encoded"/>
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="DetailReportService">
      <wsdl:port binding="impl:DetailReportSoapBinding" name="DetailReport">
         <wsdlsoap:address 
                   location="http://localhost:8080/jboss-net/services/DetailReport"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

Conclusions

If I could share anything with up and coming developers, become an open source pirate! Steal everything and choose for yourselves what works best. Take no one's word for anything. Try it all! I only showed you a bit of the code behind my Web services. SOAP requests were handled using Apache Axis. And I had to get one project to work and the first one wasn't easy. Also, Apache ANT was used to build and deploy everything.

I also used a Visual Studio package to create .NET clients for each service to give to my client. Also, if you create a client for your services, you can be sure that they work. But heed my words, mateys, there's much booty in the Open source world and guess what? Most of it is written by professionals. A lot of times, these professionals are writing boring and inefficient code for pay because some incompetent architect or manager made some bad decisions and they are stuck in a rut for some time. But, these creative guys and girls write code at night and give away their proud creations.

So, steal what you can and pillage these free downloads. Take advantage of what's out there. I'm piratepete on irc.freenode.net and some of my friends think the "pirate" name has negative connotations. I don't believe this. Open Source is free, so steal it, rob it, use it. Just don't call any of it you're own. Give credit where credit is due.

There's a good blog out there now written by Steve Jobs of Apple. He's flaming Gates something fierce. The funny part, Gates steals software and software concepts too. This is why I love Open Source, it's all in the open and I don't have to play games. If I use someone else's code to get the job done, I can get the job done, give the other guy the credit, go home, pay my mortgage, and still sleep well at night knowing I'm not part of this proprietary software nonsense.

Boy, did I get away from Session Bean Web services. Sorry. Go find some free software and be some business man or woman's IT hero. Business people are the ones that have the money. Go look for them.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)