Wednesday, August 10, 2016

An introduction to working with JAXB

I am in the process of migrating a few modules that are dependent on Apache XMLBeans to JAXB. It has been an exciting and challenging few days. I thought of jotting down a few important things I came across for anyone who might find it useful in the future.

First of all, let us look at setting up the maven plugin for the JAXB code generation. As of the time of writing this post, I came across two maven plugins;
Ended up using the first one as I found the configuration to be quite straightforward.

Your maven project structure will be as follows;
Project Folder->src->main->xsd
This will hold all the XSD files from which you would want to generate the JAXB objects.

Project Folder->src->main->xjb
This will holder your “bindings.xml” file, which is your data binding file used for any customization required as part of running the JAX generation task(xjc).

The plugin configuration for maven will be as follows;
 
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
     <version>2.2</version>
    <executions>
     <execution>
      <id>xjc</id>
      <goals>
       <goal>xjc</goal>
      </goals>
     </execution>
    </executions>
    <configuration>
     <target>2.1</target>
     
     <sources>
      <source>src/main/xsd</source>
     </sources>
     
    </configuration>
  </plugin>


  • One thing that we were quite used with XMLBeans was the “isSet” type of methods for all optional elements which will check if the element is set or not. By default JAXB does not generate this method and you have to end up using the not null condition on each element. Thankfully, the binding configuration allows for this with the following;

<jxb:bindings 
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    jxb:extensionBindingPrefixes="xjc"
    version="2.1">
<jxb:globalBindings  generateIsSetMethod="true"
</jxb:globalBindings>
</jxb:bindings>


  • By default, JAXB does not generate Java enumerations for the enumerations defined on the XSD files. The sad part is I could not find a way to apply this generation at a global level and could only handle it per XSD. But with XMLBeans, this was automatically done. In order to generate Java enumerations, the following should be done;
Sample XSD:

<xs:complexType name="EndpointType">
  <xs:attribute name="protocol">
   <xs:simpleType>
    <xs:restriction base="xs:string">
     <xs:enumeration value="HTTP"/>
     <xs:enumeration value="HTTPS"/>
     <xs:enumeration value="PAYLOAD"/>
    </xs:restriction>
   </xs:simpleType>
  </xs:attribute>
 </xs:complexType>


JAXB binding:
 
<jxb:bindings 
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    jxb:extensionBindingPrefixes="xjc"
    version="2.1">
<jxb:bindings schemaLocation="../xsd/testconfig.xsd">
       
  <jxb:bindings node="//xs:complexType[@name='EndpointType']/xs:attribute[@name='protocol']/xs:simpleType">
               <jxb:typesafeEnumClass name="Protocol" />
        </jxb:bindings>
 
   </jxb:bindings>
</jxb:bindings>

schemaLocation – This is the relative path to the XSD I want to refer to. Since my “bindings.xml” resided in the “xjb” directory, I had to go one step up and go into the XSD directory to get the required XSD file.

node – Here you need to provide the xquery path of the simple type that has the enumeration defined. If you cross check this with the XSD provided, you will figure out how the XQuery path retrieves the given element.

Note: If in any event, your xpath returns multiple elements with the same name, you can still handle this by introducing the element multiple=”true” on the <jxb:bindings> element.
E.g : <jxb:bindings node="//xs:complexType[@name='EndpointType']/xs:attribute[@name='protocol']/xs:simpleType" multiple="true">


typesafeEnumClass – On this element you can provide the Java enumeration name to be generated.

  • XMLBeans by default converts all XSD date and date time elements to a Java Calendar object. With JAXB however, by default the XMLGregorianCalendar is used. Yet again the global bindings came to the rescue and this was handled with the below configuration which converted all XSD date elements to a Java Calendar object.


<jxb:bindings 
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    jxb:extensionBindingPrefixes="xjc"
    version="2.1">

<jxb:globalBindings>

   <jxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
            parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
            printMethod="javax.xml.bind.DatatypeConverter.printDateTime"/>

        <jxb:javaType name="java.util.Calendar" xmlType="xs:date"
            parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
            printMethod="javax.xml.bind.DatatypeConverter.printDate"/>

        <jxb:javaType name="java.util.Calendar" xmlType="xs:time"
            parseMethod="javax.xml.bind.DatatypeConverter.parseTime"
            printMethod="javax.xml.bind.DatatypeConverter.printTime"/>
    </jxb:globalBindings>

</jxb:bindings>


  • If there is a need to make your JAXB objects serializable, this can be achieved with the following global binding configuration;

<jxb:bindings 
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    jxb:extensionBindingPrefixes="xjc"
    version="2.1">

 <jxb:globalBindings >
 <xjc:serializable />
  
  </jxb:globalBindings>
 
 
</jxb:bindings>




The element that does the trick is the “<xjc:serializable/>” element.


  • With JDK 1.8, I faced an issue whereby if one of your XSD’s had an import for another schema to retrieve another XSD via HTTP, this was being blocked. An excerpt of the error thrown out was “because 'http' access is not allowed due to restriction set by the accessExternalDTD property”. The work-around in this case was to use the following maven plugin to set the VM arguments required to bypass this restriction. More information on this issue can be found here.

<plugin>
    <!-- We use this plugin to ensure that our usage of the
    maven-jaxb2-plugin is JDK 8 compatible in absence of a fix
    for https://java.net/jira/browse/MAVEN_JAXB2_PLUGIN-80. -->
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>properties-maven-plugin</artifactId>
   <version>1.0.0</version>
    <executions>
        <execution>
            <id>set-additional-system-properties</id>
            <goals>
                <goal>set-system-properties</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <properties>
            <property>
                <name>javax.xml.accessExternalSchema</name>
                <value>file,http</value>
            </property>
    <property>
                <name>javax.xml.accessExternalDTD</name>
                <value>file,http</value>
            </property>
        </properties>
    </configuration>
</plugin>


That is about it. I will keep updating this post as I go on. As always, your feedback on the same is always much appreciated.

Thank you for reading, and have a good day everyone.

An introduction to the Oracle Service Bus

We are in the process of designing a new system for a telecommunication provider where we have looked at the Oracle Service Bus (OSB) to be used as the enterprise service bus. One of the first plus points for me was the amazing tooling support it encompasses. Oracle has integrated all their enterprise integration software stack into a cohesive whole by bundling it up as the Oracle SOA Suite. In this article, the focus would be on the Oracle OSB 11g which is part of the Oracle SOA Suite 11g. There are considerable changes that has been done with the new Oracle SOA Suite 12c which we will not delve into in this article. However, one feature I love about the new Oracle SOA Suite 12c is the fact that the developers can use JDeveloper to develop BPEL(Business process execution language) and OSB code in one IDE(Integrated Development Environment).

Couple of main components one needs to be aware of with the OSB is as follows;

Proxy Service
A proxy service as its name implies, is a service that is hosted to the external parties which acts as a facade for an internal service. By having a proxy service, you have more control over the changes in your internal services as the proxy service can do the required transformations if your internal services ever change.

Business Service
A business service, in terms of the OSB, represents an internal application service. It can be a WebService, JMS queue/topic, REST service, FTP service and many more. The business service will encompass the functionality to call the actual service.

So the scenario we will focus on this article is as follows;
  1. We have an internal service that returns subscriber information if the user passes in either the MSISDN or the SIM Card number and depending on the input, data will be fetched and returned.
  2. This service will have to be exposed to the external party in a more meaningful manner by making use of a proxy service.
The sample project can be downloaded here.

First of all, we create the business service which will act as the facade to our internal service. In your OSB project,  create the following four folders;
  • proxy
  • business
  • transformation
  • wsdl
Then we need to copy the internal service WSDL and the proxy service WSDL created for this example into the “wsdl” folder.

Configuring the business service
Right click on the “business” folder and select New->Business Service. When the business service is created, you will then first be presented with the “General” tab. In this we do the following;

  • Select “WSDL Web Service” and click on browser. Then select “Browse”, select the WSDL file and you will be presented with two options. Select the one ending with “(port).


  • Then go the “Transport” tab and change the URI as http://localhost:8088/mockInstalledBaseSubscriberClassificationQueryWSServiceSoapBinding. This is because we will use the SOAPUI mock service feature to test this out and the URI represents the mock service endpoint of SOAPUI for the service represented by the WSDL. 
  • The SOAPUI project use for this example can be downloaded from here.
That is all we need to do to configure our business service. Then we move onto our proxy service where all the action takes place.

Configuring the proxy service
  • Right click on the “proxy” folder created, select New->Proxy Service and provide a valid name. 
  • In the “General” tab, select “WSDL Web Service” and click on browse.
  • Now in the proxy service, you need to select the proxy WSDL file we have created which will be exposed to the external clients.























  • Go to the “Message Flow” tab. In that tab, first drag a “Route” element from the “Design Palette” on the right side. 
  • Afterwards, drag a “Routing” element into the “Route” element.
  • Click on the “Routing” element and in the bottom pane, go into the “Properties” tab where you will provide the business service that this proxy service will access and the operation name.

  • The result will be as follows;







  • Then drag a “Replace” action into the “Request Action” component.
  • Before we provide the information on the “Properties” tab for the “Replace” action, we need to create the XQuery transformation files which will map the proxy service request to the business service request and then the business service response back to the proxy service response.
  • Right click on the “transformation” folder and select New->XQuery Transformation. Enter a valid name. This should be done for both the request and response transformation files.
  • The request transformation file used is as follows;

 
(:: pragma bea:global-element-parameter parameter="$fetchSubscriber1" element="ns2:FetchSubscriber" location="../wsdl/SubscriberProxyService.wsdl" ::)
(:: pragma bea:local-element-return type="ns1:InstalledBaseSubscriberClassificationQuery/ns0:InstalledBaseSubscriberClassificationQuery" location="../wsdl/subscriber_classfication.wsdl" ::)

declare namespace ns2 = "http://www.example.org/SubscriberProxyService/";
declare namespace ns1 = "http://www.openuri.org/";
declare namespace ns0 = "http://mtnsa.co.za/si/IB/IBSubscriberClassificationQuery";
declare namespace xf = "http://tempuri.org/OSB%20training%201/transformation/subscriberrequest/";

declare function xf:subscriberrequest($fetchSubscriber1 as element(ns2:FetchSubscriber))
    as element() {
     <ns1:InstalledBaseSubscriberClassificationQuery>
        <ns0:InstalledBaseSubscriberClassificationQuery>
            <ns0:Request>
              
                    {
                        if (data($fetchSubscriber1/EquipmentType) = "MSISDN") then
                           <ns0:MSISDN>  { (data($fetchSubscriber1/EquipmentValue))}</ns0:MSISDN>
                        else 
                           <ns0:SIMCard> { data($fetchSubscriber1/EquipmentValue)}</ns0:SIMCard>
                    }

            </ns0:Request>
        </ns0:InstalledBaseSubscriberClassificationQuery>
        </ns1:InstalledBaseSubscriberClassificationQuery>
};

declare variable $fetchSubscriber1 as element(ns2:FetchSubscriber) external;

xf:subscriberrequest($fetchSubscriber1)

Here as you can see, we check if the equipment type is equal to “MSISDN” and then set the appropriate element on the business service.

  • The response transformation file used is as follows;
 
(:: pragma bea:global-element-parameter parameter="$installedBaseSubscriberClassificationQueryResponse1" element="ns1:InstalledBaseSubscriberClassificationQueryResponse" location="../wsdl/subscriber_classfication.wsdl" ::)
(:: pragma bea:global-element-return element="ns2:FetchSubscriberResponse" location="../wsdl/SubscriberProxyService.wsdl" ::)

declare namespace ns2 = "http://www.example.org/SubscriberProxyService/";
declare namespace ns1 = "http://www.openuri.org/";
declare namespace ns0 = "http://mtnsa.co.za/si/IB/IBSubscriberClassificationQuery";
declare namespace xf = "http://tempuri.org/OSB%20training%201/transformation/subscriberresponse/";

declare function xf:subscriberresponse($installedBaseSubscriberClassificationQueryResponse1 as element(ns1:InstalledBaseSubscriberClassificationQueryResponse))
    as element(ns2:FetchSubscriberResponse) {
        <ns2:FetchSubscriberResponse>
            <TradeCustomerCode>{ data($installedBaseSubscriberClassificationQueryResponse1/ns0:InstalledBaseSubscriberClassificationQuery/ns0:Response/ns0:Subscriber/@ServiceProviderCode) }</TradeCustomerCode>
            <PackageCode>{ data($installedBaseSubscriberClassificationQueryResponse1/ns0:InstalledBaseSubscriberClassificationQuery/ns0:Response/ns0:Subscriber/ns0:Package/@ProductCode) }</PackageCode>
            <PaymentOption>{ data($installedBaseSubscriberClassificationQueryResponse1/ns0:InstalledBaseSubscriberClassificationQuery/ns0:Response/ns0:Subscriber/@PaymentOption) }</PaymentOption>
        </ns2:FetchSubscriberResponse>
};

declare variable $installedBaseSubscriberClassificationQueryResponse1 as element(ns1:InstalledBaseSubscriberClassificationQueryResponse) external;

xf:subscriberresponse($installedBaseSubscriberClassificationQueryResponse1)

This is a simple transformation where we map the response elements to the proxy response elements as required.
    Now we move back to our proxy service, click on the “Replace” action, go to the “Properties” tab.
    • In the “In Variable” insert the value “body”.
    • Click on the “Expression” link. Go to the “XQuery Resources” tab, click on “Browse” and select the request transformation file.
    • In the “Variable Structures” component on the right side, expand the “body” element, and then select the request element and drag and drop it into the “Binding” text box as follows;
















    • Then select “OK” which will take you back to the “Properties” tab.
    • Select “Replace node contents” radio button. The end result will look as follows;


    • Now let us drag and drop a “Replace” action to the “Response Action” component.
    • Same as before, select the response transformation “$body/ins:InstalledBaseSubscriberClassificationQueryResponse”.
    • You will now get an error stating that the “ins” namespace is not recognized.
    • In order to resolve that, in the same “Properties” tab, select the tab “Namespaces” and click on add. Enter the prefix as “ins” and the URI as “http://www.openuri.org/”. 





    And that is it. Now we can test out the functionality. Before you do, remember to first start the mock service created on SOAP UI. 
















    Now let us log into the service bus console, go to the proxy service and launch the test console. This is the result that I got by running a sample;






















    You can see a trace of what exactly happened if you go further down on the same screen within the “Invocation Trace” section. The request and response transformation done by the OSB can be seen as follows;





















    That ends our introduction to the Oracle Service Bus. If you do have any queries on the same, please do not hesitate to leave a comment by and I will respond to it as soon as possible. Also, if there are any areas of improvement you may see, kindly leave your feedback as well which is always much appreciated.


    Tuesday, July 19, 2016

    Dev-Assurance: Hybrid between a developer and a quality assurance personnel

    Over the span of my career, I have seen many battles unfolding between the development team and the quality assurance team arguing countless hours around a defect. In the nerd-herd, these battles are the equivalent to some of the greatest battles in history minus the glorious brawls. Some people bring out their best sarcasm into the battle field though it might not be their forte.
    “Works for me” is one of the classic responses of a developer which results in something similar to the following;


    This is then followed up with a few innuendoes flying back and forth between the individuals. There can be many reasons for this such as;
    • Defect can only be re-produced in a production like environment due to it being clustered and will still work fine in the developer’s machine which runs only a stand-alone server instance.
    • Missing configuration in the test environment
    • Specific to a particular environment
    And many more which we will not go into detail as it is not the purpose of this article.

    Next comes the “Works as expected” dilemma. This is a tricky as one can look at it in different angles and come into different conclusions. In terms of the developer, if it was never specified as a requirement then it should not be a valid defect. In terms of the quality assurance person, it’s a non-functional requirement which should have been catered to in the solution delivered. 

    Defects can take many forms but the end result is that most often they result in a conflict between the developer and the tester. In my career, I too have been in these unpleasant confrontations. If one actually looks at those situations in retrospection, one will see that there is always an issue of egoism in play which results in both parties not giving up their own standpoints. My father gave me one very important quote framed which I still keep at my desk. Think its best I show it to you;

    Keeping all these SLAs, defect ratios, defect density measures aside, if you really look at the issue, for me as a developer, I would not want the testers to find any defects in my code. But we all know that 100% perfect code is as easy as finding a unicorn. What I am trying to get at here is a change in mindset to a reported defect in terms of a developer. You have to know that you will never produce zero defect code every time. When you do get a defect reported on the code you have worked on, it is best to take it as a learning opportunity and to build more self-awareness of what you need to do in the future to avoid such issues and move forward rather than get in a fruitless battle with the tester trying to defend the defect. Quality is something that should be instilled in you as a developer and one of the first steps in moving in that direction is to stop thinking as a developer when you are testing your own code. Often times we get over concerned on the technical details of the code and the code coverage with respective the branches you have tested. Don’t take me wrong, this is well and good, but what I am trying to get to is the fact that you need to look at the business functionality that your code is providing in the end and if it does that satisfactorily. 

    I just love proactive approaches to software development, so where I work, we have put in a few quality gates that have substantially reduced these unpleasant confrontations between the two teams which in essence should be considered as one team with one aim which is to deliver quality solutions to the customer.

    Design Reviews
    In this stage what we do is, as a team, go through the design document created for a given feature or functionality. As we follow an agile process, a design document has features broken down into user stories. When we get the whole team involved in the design review, it brings out different opinions and concerns which provide invaluable information to better refine the solution. This has resulted in a reduction in the defect density and has improved the communication between the individuals as everyone has the context of the work carried out though everyone may not be involved in a given design implementation.

    Demo/walk-through
    After a particular implementation is completed, we have made it a habit that the developers involved in it should present their deliverable to the team before it is released to the testing environment. As this again involves the whole team, the team can openly discuss any issues or provide suggestions for improvement which can then be considered prior to the release to the test environment. In one aspect, this gives the developers an understanding of the business impact of the solution they provide so they can relate more closely with it and of course allows them to fine tune their soft skills in presentation as well.

    Release audit
    This is where we have a technical lead or an architect ask specific questions prior to the actual release. Questions such as;
    • What was the total effort for this release (to ascertain the amount of change going into a release)
    • Was code review completed and review comments addressed?
    • Is testing completed successfully?
    • How many positive and negative scenarios were identified during the test stage?
    • Any non-functional requirements considered for the release?
    • Regression testing completed for the core functionality?
    • Any major deployment changes on this release?
    All these questions allows the team to ponder on aspects they might not have considered and acts as a quality gate just prior to the actual deployment.
    These stages has allowed a developer to embed the quality aspect into their core as the Samaritan in the person of interest did to monitor everyone’s keystrokes by building a virus into the firmware of all hardware (I’m just not over the fact that this great TV series came to an end). This in turn allows us to create “dev-assurance” personnel in our team which in turn has improved our team’s productivity, communication and efficiency.

    Monday, March 7, 2016

    Few maven tips and tricks

    I was working on migrating an existing application that was using WebLogic Workshop (yes you read it right, using an IDE that is out of support) to maven. There were a few gotchas during the journey which i wanted to jot down here for anyone who might find it useful and specially for myself just as a reference.

    The overall application was using Apache XMLBeans to deal with everything to do with XML and this was the first part I was migrating to maven. Maven did have a maven plugin for XMLBeans and the following snippet explains how you can incorporate this plugin to your project;


     
     <build>
        <plugins>
    
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>xmlbeans-maven-plugin</artifactId>
            <version>2.3.3</version>
      <configuration> 
       <javaSource>1.5</javaSource> 
       </configuration> 
            <executions>
            <execution>
             <phase>generate-sources</phase>
                <goals>
                  <goal>xmlbeans</goal>
                </goals>
            </execution>
            
          
            </executions>
          </plugin>
        </plugins>
      </build>
    

    The one gotcha here is that you need to use the <javaSource>1.5</javaSource> tag if you want the XMLBeans code generated to have the "List" data structure for elements that have a maxoccurs set to unbounded. This is only if your code is already using the list type. Without this tag, this plugin will just generate the Array type for the unbounded elements.

    Next up, it was the time to migrate the modules which exposed the web services of the application. As this was running on WebLogic, it used the "jwsc" task to generate the require artifact. I could not find an out of the box maven plugin which catered for this requirement and after some searching around I came across the solution where an ant build was invoked via the maven ant run plugin. Let us look at the configuration changes required on the pom.xml;


     
    <plugin>
          <groupId>org.codehaus.gmaven</groupId>
          <artifactId>gmaven-plugin</artifactId>
          <version>1.3</version>
          <executions>
            <execution>
              <id>set-main-artifact</id>
              <phase>package</phase>
              <goals>
                <goal>execute</goal>
              </goals>
              <configuration>
                <source>
                  project.artifact.setFile(new File(project.build.directory+'/'+project.artifactId+'-'+project.version+'.war'))
                </source>
              </configuration>
            </execution>
          </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.6</version>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                    <configuration>
                        <target>
                            <property name="maven.compile.classpath" refid="maven.compile.classpath" />
                            <property name="maven.runtime.classpath" refid="maven.runtime.classpath" />
                            <property name="maven.test.classpath" refid="maven.test.classpath" />
                            <property name="maven.plugin.classpath" refid="maven.plugin.classpath" />
                            <ant antfile="src/main/ant/build.xml" target="all" />
                        </target>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>org.apache.ant</groupId>
                    <artifactId>ant</artifactId>
                    <version>1.7.1</version>
                    <scope>runtime</scope>
                </dependency>
                <dependency>
                    <groupId>ant-contrib</groupId>
                    <artifactId>ant-contrib</artifactId>
                    <version>1.0b2</version>
                    <scope>runtime</scope>
                </dependency>
                <dependency>
       <groupId>weblogic</groupId>
       <artifactId>weblogic</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
       <dependency>
       <groupId>weblogic</groupId>
       <artifactId>xmlbeans</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
       <dependency>
       <groupId>weblogic</groupId>
       <artifactId>wlserv</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
       <dependency>
       <groupId>weblogic</groupId>
       <artifactId>jaxwsrt</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
       <dependency>
       <groupId>weblogic</groupId>
       <artifactId>beadescriptor</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
      <dependency>
       <groupId>weblogic</groupId>
       <artifactId>beadescriptorbinding</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
      <dependency>
       <groupId>weblogic</groupId>
       <artifactId>beadescriptorsettable</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
      <dependency>
       <groupId>weblogic</groupId>
       <artifactId>staxb</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
       <dependency>
        <groupId>org.apache.xmlbeans</groupId>
        <artifactId>xmlbeans</artifactId>
        <version>2.4.0</version>
      </dependency>
      <dependency>
       <groupId>weblogic</groupId>
       <artifactId>webservices</artifactId>
       <version>10.3.0</version>
       <scope>compile</scope>
      </dependency>
                <dependency>
                    <groupId>com.sun</groupId>
                    <artifactId>tools</artifactId>
                    <version>1.5.0</version>
                    <scope>system</scope>
                    <systemPath>${java.home}/../lib/tools.jar</systemPath>
                </dependency>
            </dependencies>
        </plugin>
        
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
               
                <executions>
                      <execution>
                          <id>default-war</id>
                          <phase>none</phase>
                      </execution>
                  </executions>
                 
            </plugin>
    

    Note that the dependency items with the groupId set with "weblogic" was installed on the maven repository manually using the maven install file command. The jar libraries required are as follows;


    • wlfullclient.jar (this jar was built as per the instructions specified here)
    • webserviceclient.jar
    • webservices.jar
    • wls-api.jar
    • xercesImpl.jar
    • xmlParserAPIs.jar
    • com.bea.core.descriptor.settable.binding_1.4.0.0.jar
    • com.bea.core.descriptor.wl.binding_1.1.0.0.jar
    • com.bea.core.descriptor.wl_1.1.0.0.jar
    • com.bea.core.xml.beaxmlbeans_1.0.0.0_2-4-0.jar
    • com.bea.core.xml.staxb.buildtime_1.3.0.0.jar
    • glassfish.jaxws.rt_2.1.3.jar
    The next step is to drop the ant build.xml on to the src/main/ant directory of your project. The build.xml is as follows;


     
    <project name="build-webservice" default="all">
    
        <target name="all" depends="build.webService" />
    
        <path id="maven_plugin_classpath">
            <pathelement path="${maven.plugin.classpath}" />
        </path>
    
        <path id="maven_runtime_classpath">
            <pathelement path="${maven.compile.classpath}" />
            <pathelement path="${maven.runtime.classpath}" />
            <pathelement path="${maven.plugin.classpath}" />
            <pathelement path="${weblogic.jar}" />
        </path>
    
        <taskdef name="jwsc"
                 classname="weblogic.wsee.tools.anttasks.JwscTask"
                 classpath="${weblogic.jar}"
                 classpathref="maven_plugin_classpath"
        />
    
        <target name="build.webService" description="Compile the web services if not up2date">
            <!--
                Eclipse compiles and places classes into target/classes when the workspace is building.
                If this folder exists when jwsc runs, then any classes that are already compiled will NOT
                be included in the final WAR file.  Thus, this directory is removed prior to created the
                webServices WAR fie.
            -->
            <delete dir="target/classes" />
            <jwsc srcdir="${project.build.sourceDirectory}"
                  destDir="target"
                  classpathref="maven_runtime_classpath"
                  keepGenerated="yes"
                  applicationxml="${project.build.directory}/application.xml"
                  fork="true"
                  memorymaximumsize="256m"
                  verbose="true"
                  debug="on"
            >
                <module contextPath="ws" name="${project.artifactId}-${project.version}">
                    <jwsfileset srcdir=".">
                       <include name="**/*.java" />
                       <exclude name="**/*Test.java" />
                     </jwsfileset>
                </module>
            </jwsc>    
        </target>    
    </project>
    

    Note that there are no changes required to be made on this build.xml.

    Next up, it was about building the EAR module to be deployed to weblogic. Looking at the EAR built up by WebLogic Workshop, I could see that all the required third-party libraries were being bundled up into a folder called APP-INF/lib which was located in the root directory of the EAR. Also the WAR files did not have any jar files in the lib directory and I wanted to mimic this functionality when building the EAR using maven. The following configuration allowed me to do that;

     
     <build>
      <finalName>ErrorXAEAR</finalName>
        <plugins>
          <plugin>
            <artifactId>maven-ear-plugin</artifactId>
            <version>2.10.1</version>
            <configuration>
              <defaultLibBundleDir>APP-INF/lib/</defaultLibBundleDir>
              <skinnyWars>true</skinnyWars>
        <modules>
                 <jarModule>
                  <groupId>mtn.sa.errorxa</groupId>
           <artifactId>errorxa-ejb</artifactId>
                   <bundleDir>/</bundleDir>
           <bundleFileName>ErrorXAEJB.jar</bundleFileName>
                 </jarModule>
           <webModule>
                   <groupId>mtn.sa.errorxa</groupId>
           <artifactId>errorxa-service</artifactId>
                   <bundleDir>/</bundleDir>
           <bundleFileName>ErrorXAService.war</bundleFileName>
                 </webModule>
              </modules>
            </configuration>
      
          </plugin>
        </plugins>
      </build>
    

    The tag <skinnyWars> is what enables the lib directory of the war file not be populated with the third-party libraries required which is now bundled up in the APP-INF/lib directory on the EAR. The tag <defaultLibBundleDir> handles copying all required libraries to a folder called APP-INF/lib within the EAR.

    One other thing with respect to the generation of the EAR is that I did not want maven to generate the application.xml file as this file along with the weblogic-application.xml was already generated on the project and I wanted use the same. To achieve this, all i had to do was to drop both those files into the folder src/main/application and the default application.xml was overridden.

    I found the mvn dependency:tree tool of maven to be quite useful when building up the EAR to identify and remove the unnecessary dependencies being dragged into the EAR via recursive dependencies. With a simple exclusion tag I was able to remove the unwanted libraries.

    That is about it for this post. I will keep updating the post with any things I may come across. The next step is to use maven to do the deploy and un-deploy of each application as part of the build process.

    Monday, January 25, 2016

    Integrating JQGrid with Spring MVC and Gson

    I was working on a single page application where i wanted to use the grid functionality in one part of the application which was using Spring MVC. It has been some time since i last used JQGrid and finding the information required to get me up and about was bit of a challenge. On this post, I wanted to collate all the information and put it into a tutorial to follow so anyone who might be using the same functionality might find it helpful to setup JQGrid.

    First of all, we will setup a sample web project on Eclipse and define the web.xml as follows;


     
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
      <display-name>JQGridExample</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
      
      <servlet>
            <servlet-name>JQGridExample</servlet-name>
            <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
            </servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>JQGridExample</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
        
     
    </web-app>
    

    To wire up Spring MVC, I have registered the DispatcherServlet to be loaded on start-up. This is basically how you will register any Spring MVC application. Next up, we need to create the spring configuration to register the required components/elements of our spring MVC application.

    In this instance, I have kept the spring context file name to the "servlet-name" given on my web.xml because by default when the spring container loads up, it will look for a file with the format <servletname>-servlet.xml

    If you want to use any other name you want for your spring context configuration file, you can do so. You just need to register the context loader on your web.xml.

    So let us see how our spring context configuration file looks like;


     
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:mvc="http://www.springframework.org/schema/mvc"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
     http://www.springframework.org/schema/mvc
     http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">
     
        <context:component-scan base-package="com.example.jqgrid.controller" />
         <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
        </bean>
        
        <mvc:resources mapping="/resources/**" location="/resources/"/>
        
        
        <mvc:annotation-driven/>
     
        
    </beans>
    

    We first register the package that contains all our controller classes. In this instance it will be just one controller. With the component-scan element, it will scan all classes under the "controller" package.

    Next up, we tell the Spring container how to resolve our JSP files. In this instance the internal view resolver is being used and we provide the location of where our JSP files reside on the application.

    The next interesting part on this configuration is the <mvc:resources> element. The reason to define this is to let the Spring container know about our static resources such as the javascript files, images, stylesheets. If we do not define them as resources, whenever you refer a javascript file for example in your application, spring mvc will try to match an existing controller by looking at the defined URL patterns. In this case, all my css, javascript,image files reside under the resources folder.

    I then define the index.jsp which is the entry point into our application. Now I do not want to do anything on this page and i simply re-direct it to a different page which is resolved via spring-mvc. Our index.jsp file is as follows;


     
    <script type="text/javascript">
     window.location.replace("jqGridExample");
    </script>
    

    I am simply re-directing the URL to jqGridExample. Now to understand how this is resolved from spring-mvc, we will need look at our controller class. Our controller class is as follows;


     
    package com.example.jqgrid.controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    import com.example.jqgrid.common.util.JsonUtil;
    import com.example.jqgrid.dto.JQGridDTO;
    import com.example.jqgrid.dto.SuperHeroDTO;
    import com.example.jqgrid.handler.JQGridHandler;
    
    /**
     * This class acts as the controller for JQGrid related functionality.
     * 
     * @author Dinuka Arseculeratne
     * 
     */
    @Controller
    public class JQGridController {
    
     /**
      * This method will display the page used to display the grid.
      * 
      * @param req
      * @param res
      * @return
      */
     @RequestMapping(method = { RequestMethod.POST, RequestMethod.GET }, path = "/jqGridExample")
     public String jqGrid(HttpServletRequest req, HttpServletResponse res) {
      String forward = "jqgrid/jqGridData";
    
      return forward;
     }
    
     /**
      * This method will handle fetching data required for the JQGrid.
      * 
      * @param req
      * @param res
      * @return
      */
     @RequestMapping(method = { RequestMethod.POST, RequestMethod.GET }, path = "/loadData")
     public String loadData(HttpServletRequest req, HttpServletResponse res) {
      String forward = "common/formData";
    
      JQGridDTO<SuperHeroDTO> gridData = new JQGridHandler().loadSuperHeroes(req);
      req.setAttribute("formData", JsonUtil.toJsonObj(gridData));
      return forward;
     }
    
    }
    
    
    

    So if we look at the first method, you can see we are simply return a text called "jqgrid/jqGridData". Now to understand what this does, we need to go back and look at our spring context configuration file. In that we specified that all our JSP files reside in the "WEB-INF/jsp" folder and the suffix is ".jsp". So in this instance the path we return from this method tells the spring container that the JSP to be returned is in fact in "WEB-INF/jsp/jqgrid/jqGridData.jsp". Note that we did not need to specify the suffix as ".jsp" because we already configured that on our spring context configuration.

    We will come back to the second method after we look at our page where we have defined the JQGrid. The jqGridData.jsp is as follows;


     
    <!DOCTYPE html>
    <html>
     <head>
      <title>JQGrid Example</title>
    
       
        <link href="resources/css/jquery-ui.css" rel="stylesheet">
        <link href="resources/css/jquery-ui.theme.css" rel="stylesheet">
        <link href="resources/css/jquery-ui.structure.min.css" rel="stylesheet">
        <link rel="stylesheet" href="resources/css/ui.jqgrid.css">
        
     </head>
     
    <body>
    
    <div>
     
       <table id="list">
                    <tr>
                            <td />
                    </tr>
            </table>
            <div id="pager"></div>
            <div style="margin-top:10px;">
            <input type="button" id="showSelected" value="Show Selected"/>
            </div>
     
     
    </div>
    
      <script src="resources/js/jquery-1.11.1.min.js"></script>
      <script src="resources/js/jquery-ui.min.js"></script>
      <script src="resources/js/i18n/grid.locale-en.js"></script>
      <script src="resources/js/jquery.jqGrid.min.js"></script>
      
      
    <script type="text/javascript">
    
     $(document).ready(function(){
      $("#list").jqGrid({
                    url : "loadData",
                    datatype : "json",
                    mtype : 'POST',
                    colNames : [ 'Name','Alias','Super Power'],
                    colModel : [ {
                            name : 'name',
                            index : 'name',
                            width : 150
                    }, {
                            name : 'alias',
                            index : 'alias',
                            width : 150,
                            editable : false
                    }, {
                            name : 'power',
                            index : 'power',
                            width : 550,
                            editable : false
                    }],
                    pager : '#pager',
                    rowNum : 10,
                    height: 'auto',
                    rowList : [ 10 ],
                    sortname : 'invid',
                    sortorder : 'desc',
                    viewrecords : true,
                    gridview : true,
                    multiselect: true,
                multiboxonly: false,
                    caption : 'Super Heroes',
                    jsonReader : {
                            repeatitems : false,
                    }
            });
            jQuery("#list").jqGrid('navGrid', '#pager', {
                    edit : false,
                    add : false,
                    del : false,
                    search : false
            });
            
            
            $('#showSelected').on('click',function(){
             
             var selRowArr = jQuery("#list").getGridParam('selarrrow');
             var selectedAppIds = [];
             for(var i=0;i<selRowArr.length;i++){
              var celValue =  $('#list').jqGrid('getCell', selRowArr[i], 'alias');
              selectedAppIds.push(celValue);
             }
             alert(selectedAppIds);
             $('#list').trigger( 'reloadGrid' );
             
       
            });
     
     });
    </script>
    
    </body>
    </html>
    

    First of all, we need to define the element on which the JQGrid will be loaded. In this instance that is the HTML table element with the id of  "list". And since we want the pagination ability, we define our pagination section below the grid. In this instance, the pagination section is defined with the div with the id of "pager".

    We then look at the java script code as the bottom. Here we load the JQGrid by calling the method jqGrid() passing in the required attributes. I will not be explaining all the attributes defined here as there are many more which i have not used in this instance. The most relevant attributes for this tutorial will be explained. So first off, the URL. This is defined as "loadData". We need to go back our controller class to understand how this is mapped.

    On the controller, we have defined the second method as "loadData" which fetches the data required for the grid. Now the interesting part is, JQGrid expects the data sent across in a particular format. To adhere to this format, i have defined a class to hold this structure which is defined as JQGridDTO. Let us see how that class looks like;


     
    package com.example.jqgrid.dto;
    
    import java.io.Serializable;
    import java.util.List;
    
    /**
     * This class acts as common template for all pages that use the JQGrid.
     * 
     * @author Dinuka Arseculeratne
     * 
     * @param <T>
     */
    public class JQGridDTO < T extends Serializable > {
    
        private int page;
    
        private String total;
    
        private String records;
    
        private List<T> rows;
    
        public int getPage() {
            return page;
        }
    
        public void setPage(int page) {
            this.page = page;
        }
    
        public String getTotal() {
            return total;
        }
    
        public void setTotal(String total) {
            this.total = total;
        }
    
        public String getRecords() {
            return records;
        }
    
        public void setRecords(String records) {
            this.records = records;
        }
    
        public List<T> getRows() {
            return rows;
        }
    
        public void setRows(List<T> rows) {
            this.rows = rows;
        }
    
    }
    
    

    This is the structure of the data required by JQGrid. I have kept the rows data structure generic in order to be able to use this same class to pass different types of data to the grid as required. It can be any type of object as long as it implements the Serializable interface.

    So I am a big time super heroes fan, and hence in this instance I will be displaying some information on some of the super heroes. I have included super heroes from both the DC and Marvel universe to keep everyone happy.

    So let us look at our data object and the handler class which will load our data;

     
    package com.example.jqgrid.dto;
    
    import java.io.Serializable;
    
    /**
     * 
     * @author Dinuka Arseculeratne
     *
     */
    public class SuperHeroDTO implements Serializable {
    
     /**
      * 
      */
     private static final long serialVersionUID = 1420635747715993129L;
    
     private String name;
     private String alias;
     private String power;
    
     public SuperHeroDTO(String name, String alias, String power) {
      this.name = name;
      this.alias = alias;
      this.power = power;
     }
    
     public String getName() {
      return name;
     }
    
     public void setName(String name) {
      this.name = name;
     }
    
     public String getAlias() {
      return alias;
     }
    
     public void setAlias(String alias) {
      this.alias = alias;
     }
    
     public String getPower() {
      return power;
     }
    
     public void setPower(String power) {
      this.power = power;
     }
    
    }
    
    


     
    package com.example.jqgrid.handler;
    
    import java.util.LinkedList;
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    
    import com.example.jqgrid.dto.JQGridDTO;
    import com.example.jqgrid.dto.SuperHeroDTO;
    
    /**
     * The handler class used to fetch the data required.
     * 
     * @author Dinuka Arseculeratne
     *
     */
    public class JQGridHandler {
    
     /**
      * This method will fetch the super hero list. Of course i have mixed and
      * matched DC and Marvel in order to keep peace on the universe.
      * 
      * @return
      */
     public JQGridDTO<SuperHeroDTO> loadSuperHeroes(final HttpServletRequest req) {
      /**
       * The page and rows are sent from the JQGrid component with the Ajax
       * query.
       * 
       */
      int page = Integer.valueOf(req.getParameter("page")).intValue();
      int pageSize = Integer.valueOf(req.getParameter("rows")).intValue();
    
      /**
       * I am not using the star index and end index in this case, but in an
       * ideal situation, you will be passing the start and end index to your
       * pagination SQL query.
       * 
       */
      int startIndex = page == 1 ? 0 : (pageSize * (page - 1));
      int endIndex = page == 1 ? pageSize : pageSize * page;
      int total = -1;
    
      JQGridDTO<SuperHeroDTO> jqGridData = new JQGridDTO<SuperHeroDTO>();
      List<SuperHeroDTO> superHeroList = new LinkedList<SuperHeroDTO>();
      SuperHeroDTO flash = new SuperHeroDTO("Barry Allen", "Flash", "Super speed, Taping into the speed force");
      superHeroList.add(flash);
    
      SuperHeroDTO superMan = new SuperHeroDTO("Clark Kent", "Superman", "Flying, super speed");
      superHeroList.add(superMan);
    
      SuperHeroDTO batman = new SuperHeroDTO("Bruce Wayne", "Batman", "Cool toys, Intelligence");
      superHeroList.add(batman);
    
      SuperHeroDTO professorX = new SuperHeroDTO("Professor Xavier", "Professor X", "Mind control");
      superHeroList.add(professorX);
    
      /**
       * The total in the ideal situation would be the count of the records of
       * your SQL query from the table you want to fetch data from.
       * 
       */
      total = superHeroList.size();
    
      jqGridData.setPage(page);
      jqGridData.setTotal(String.valueOf(Math.ceil((double) total / pageSize)));
      jqGridData.setRecords(String.valueOf(total));
      jqGridData.setRows(superHeroList);
      return jqGridData;
     }
    }
    
    


    Typically you will be using a database to fetch your data. To maintain the brevity of this tutorial i have just loaded up static data. On the code comments I have mentioned how you would be passing the data when using an actual database.

    In this instance, the JQGrid is setup to receive the data in JSON format. So to convert our super hero object to its JSON equivalent, i have used Google's GSON library. I wrote a helper class to convert JSON objects to Java objects and Java objects to JSON objects which I have shared in one of my previous articles which you can find here.

    I have not used the spring-mvc default functionality to send a JSON response. In this example what I do is set the JSON output in a request attribute and then forward the page to a common page where it just prints out that attribute and the response is sent back on the Ajax request made by the JQGrid component. This common page is defined as follows;


     
    <%=request.getAttribute("formData")%>
    


    Going back to our JSP file which defined the JQGrid, the next important attribute I want to focus on is the "colModel". This maps the data sent on your JSON output to the grid columns that are displayed. In this instance you can see the names mentioned here are the instance variable names defined on our super hero data object. The rest of the attributes are self-explanatory so I will not delve into the details on those attributes.

    Another important use case I required was to be able to send the selected rows to the back-end. To do this, you can use the in-built JQGrid functions. The following code shows the code which retrieves the name of the super hero on all selected rows (in this case as the multi select feature is enabled on the grid) and puts it into a Java script array.


     
     $('#showSelected').on('click',function(){
             
             var selRowArr = jQuery("#list").getGridParam('selarrrow');
             var selectedAppIds = [];
             for(var i=0;i<selRowArr.length;i++){
              var celValue =  $('#list').jqGrid('getCell', selRowArr[i], 'alias');
              selectedAppIds.push(celValue);
             }
             alert(selectedAppIds);
             $('#list').trigger( 'reloadGrid' );
             
       
            });
    

    And that ends by tutorial on how to setup JQGrid with Spring MVC and Gson. The working code is checked into my GIT repository and can be found here. You can clone the repository if required and run the application.