Bo's blog

Saturday, November 21, 2009

Using JAX-WS with Maven

 

(Copied from: http://java.sun.com/mailers/techtips/enterprise/2008/TechTips_Jan08.html)

Welcome to the Enterprise Java Technologies Tech Tips for January 18, 2008. Here you'll get tips on using enterprise Java technologies and APIs, such as those in Java Platform, Enterprise Edition (Java EE).

You can now read the Enterprise Java Technologies Tech Tips online as a web log.

This issue covers using JAX-WS with Maven.

This tip was developed using an open source reference implementation of Java EE 5 called GlassFish v2 and the open source NetBeans IDE 6.0. You can download GlassFish v2 from the GlassFish Community Downloads page. You can download NetBeans IDE 6.0 from the NetBeans page.

Any use of this code and/or information below is subject to the license terms.

Using JAX-WS with Maven

By Rama Pulavarthi

Java API for XML-Based Web Services, JAX-WS, is a fundamental technology for developing SOAP-based and RESTful Java Web services, and is a key part of project Metro, the web services technology stack in GlassFish. In addition to providing a high performance runtime, JAX-WS offers the wsimport and wsgen tools for creating web services and web service clients. The wsimport tool takes as input a Web Services Definition Language (WSDL) file and generates JAX-WS portable artifacts such as a service endpoint interface (SEI). The wsgen tool reads a web service endpoint class and generates all the required artifacts for web service deployment and invocation.

You can access wsimport and wsgen through the GlassFish command line interface (CLI). You can also access the tools through Ant tasks or through a Maven plugin. In this tip, you'll learn how to use the JAX-WS Maven plugin to develop web services.

Maven

Maven is a highly configurable framework that you can use to manage various aspects of a project's life cycle, from building and deploying an application to document generation and project management. Maven, like Ant, is a very popular development tool due to its standardized project layout and dependency management mechanism. By following standard conventions for project layout and using common defaults for building lifecycle phases such as compilation and packaging, you can create projects that are easy to understand and manage. Maven uses Project Object Model (POM) to describe project-related information. Unlike Ant, in which you need to define how projects are built and deployed, all Maven projects implicitly share a set of plugins for doing well-defined tasks such as building and packaging. These plugins can also be configured to change default behavior and change build order as needed.

For more information about Maven, see Welcome to Maven and Building Web Applications with Maven 2.

JAX-WS Maven Plugin

As mentioned previously, JAX-WS provides two tools for web services development: wsimport and wsgen. The JAX-WS Maven plugin provides Maven adapters for these tools. The plugin offers the tools' functionality as two goals jaxws:wsimport and jaxws:wsgen. A goal is roughly the Maven equivalent of an Ant task. For each of the two goals, the plugin accepts all the configuration options that can be passed to corresponding CLI or Ant tasks.

For the jaxws:wsimport goal, the plugin reads a WSDL file and generates Java classes required for web service creation, deployment, and invocation. The jaxws:wsimport goal is automatically executed within the life cycle phase generate-sources. By default, the plugin looks for WSDL files in the ${basedir}/src/wsdl directory. You can optionally specify the location of the WSDL files by configuring the wsdlLocation parameter. You can see descriptions of all the jaxws:wsimport configuration parameters on the JAX-WS commons page for jaxws:wsimport.

For the jaxws:wsgen goal, the plugin reads an SEI class and generates all of the portable artifacts for the JAX-WS web service. The jaxws:wsgen goal is automatically executed within the life cycle phase process-classes. The plugin requires that you set the sei parameter for the jaxws:wsgen goal, which specifies the service endpoint implementation class name. The plugin can optionally generate a service description, that is a WSDL file, from the service endpoint implementation class if you specify the genWsdl parameter. However, the genWsdl parameter is optional -- the JAX-WS runtime can dynamically generate the WSDL after deployment. You can see descriptions of all the jaxws:wsgen parameters on the JAX-WS commons page for jaxws:wsgen.

The jaxws:wsimport and jaxws:gen goals are executed implicitly when the corresponding life cycle phase is run. Optionally, the plugin can be explicitly run by specifying a goal such as jaxws-maven-plugin:wsimport. You can get more information about the Maven build life cycle phases and execution in Introduction to the Build Lifecycle.

Why Use the JAX-WS Maven Plugin Instead of Ant?

The advantage of using the JAX-WS Maven plugin instead of Ant tasks is that you don't have to get the JAX-WS dependencies, set up the classpath, and configure and invoke the tool tasks for compilation and packaging -- steps required by the Ant tasks. Maven automatically downloads all dependencies, makes them available to your application, and plugs them into the build life cycle phase. You might however need to do some tweaking of the configuration to make the plugins behave in a preferred way.

For more information about the JAX-WS Maven plugin as well as other JAX-WS tools, see the Metro Tools page.

JAX-WS Maven Sample

Now that you've learned some of the basics of the JAX-WS Maven plugin, let's look at a sample application that uses the plugin to create a web service and web service client. The NetBeans IDE supports Maven 2 project management (Maven 2 is the current version of Maven) through a plugin. You can use the plugin within the IDE to create Maven-based projects, execute Maven commands by associating IDE actions to Maven goals, browse a repository, add dependencies, and do hot deployment of web applications with a few mouse clicks.

You can also perform some of these tasks manually by running Maven and editing the configuration in the POM file. However, the NetBeans IDE offers an easier, more automated way to generate and configure POMs. Because of this the sample in this tip uses NetBeans IDE 6.0.

A package that contains the code for the sample application accompanies the tip. As you build the sample application using the instructions below, you can compare the files that you create to those in the package.

Initial Setup

Before you install and run the sample, you need to do some initial setup as follows:

  1. If you haven't already done so, download and install the following:
    Also, to run the sample with JDK 6 prior to the JDK 6 Update 4 release, you need use the endorsed override mechanism by copying the jaxb-api.jar and jaxws-api.jar files to <java-home>/lib/endorsed, where <java-home> refers to the directory in which the runtime software is installed -- this is the top-level directory of the Java SE Runtime Environment or the jre directory in the JDK. If you run the sample with JDK 6 Update 4 or later, you do not need to use the override mechanism.
  2. If you downloaded GlassFish v2 separately, register it in NetBeans as follows:
    • Right-click on the Servers node in the Services window.
    • Select Add Server.
    • Leave the Server as Sun Java System Application Server.
    • Click the Next button.
    • Click the Browse button and browse to the location that you installed GlassFish V2.
    • Click the Choose button.
    • Click the Next button.
    • Set the Admin Password to the default, adminadmin, unless you chose a different password for GlassFish v2.
    • Click the Finish button.
  3. Install the Mevenide2-Netbeans plugin, which provides support in NetBeans for Maven 2 projects, as follows:
    • Select Plugins from the Tools menu.
    • Select the Available plugins tab in the Plugins window.
    • Select the Maven plugin.
    • Click the Install button.

Creating the Project and Subprojects

In this sample, you create a main project, that is, a parent project, named jaxws-maven-sample. The parent project has two subprojects: HelloService, for the web service, and HelloClient, for the web service client. Here is what the project structure looks like:

   jaxws-maven-sample (POM Project)
     helloservice (WAR project)
     helloclient (JAR Project)

To reduce redundancy, the parent project POM holds configuration parameters that are in common between HelloService and HelloClient. To create the project and subprojects, do the following:

  1. Create the parent (POM project), jaxws-maven-sample.
    • Select New Project from the File menu.
    • Choose the Maven category then the Maven project.
    • Click the Next button.
    • Select the Maven Quickstart Project archetype (the default).
    • On the next screen specify the following project settings, also known as Maven project coordinates:
          - ProjectName: jaxws-maven-sample
          - ProjectLocation: Specify a directory to contain the project, for example, Users/ramapulavarthi.
          - Version: 1.0-SNAPSHOT
          - GroupId: com.example.maven.jaxws
          - Package: com.example.maven.jaxws
    • Click the Finish button to create the project.

    You should now see the project in NetBeans Projects window.
  2. Change the project properties from jar to pom.
    • Right-click the jaxws-maven-sample in the Projects window.
    • Select the Properties option from the menu.
    • In the General category, change the Packaging value from jar to pom.
    • Click the OK button. Notice that the entry in the Projects window now shows jaxws-maven-sample (pom).
  3. Remove unwanted dependencies and files created by default. Because this is a POM project, it will have submodules instead of sources/tests. So you need to remove sources from the project. Also, there are no unit tests in this project so you need to remove any JUnit dependencies.
    • Click the Files tab (next to Projects tab).
    • In the Files window, right-click the src directory below jaxws-maven-sample and choose Delete.
    • In the Projects window, expand the TestLibraries node of jaxws-maven-sample, right-click on the junit-3.8.1.jar, and select Remove Dependency.
  4. Change the source to Java 5. You need Java 5 to create web services. However, the default is Java 1.4.
    • Right-click the jaxws-maven-sample in the Projects window.
    • Select the Properties option from the menu.
    • In the Sources category, change the Source/Binary Format value from 1.4 to 1.5.
    • Click the OK button.

    If you examine the pom.xml file in the Project Files below jaxws-maven-sample, you'll notice the configuration source and target values are changed to 1.5.
  5. Create the subproject (WAR project), helloservice.
    Repeat the steps in step 1, "Create the parent (POM project), jaxws-maven-sample" except instead of selecting the Maven Quickstart Project archetype, select Maven WebApp archetype. Also specify the settings as follows:
           - ProjectName: helloservice
           - ProjectLocation: Specify the directory that contains the jaxws-maven-sample project, for example, /Users/ramapulavarthi/jaxws-maven-sample.
           - Version: 1.0-SNAPSHOT
           - GroupId: com.example.maven.jaxws
           - Package: com.example.maven.jaxws.helloservice
    • Click the Finish button to create the project.
      You should now see helloservice Maven Webapp (war) in the NetBeans Projects window. Notice that the pom.xml file for helloservice has a reference to the parent project, jaxws-maven-sample, and the pom.xml file for jaxws-maven-sample now specifies a module for helloservice.
  6. Remove unwanted dependencies and files for helloservice.
    • Click the Files tab (next to Projects tab).
    • In the Files window, expand the src directory below helloservice Maven webapp, right-click the test directory and choose Delete.
    • In the Projects window, expand the TestLibraries node of helloservice Maven webapp, right-click on junit-3.8.1.jar, and select Remove Dependency.
  7. Create the subproject (JAR project), helloclient.
    Repeat the steps in step 1, "Create the parent (POM project), jaxws-maven-sample" except specify the settings as follows:
           - ProjectName: helloclient
           - ProjectLocation: Specify the directory that contains the jaxws-maven-sample project, for example, /Users/ramapulavarthi/jaxws-maven-sample.
           - Version: 1.0-SNAPSHOT
           - GroupId: com.example.maven.jaxws
           - Package: com.example.maven.jaxws.helloclient
    • Click the Finish button to create the project.
      You should now see helloclient (jar) in the NetBeans Projects window. Notice that the pom.xml file for helloclient has a reference to the parent project, jaxws-maven-sample, and the pom.xml file for jaxws-maven-sample now specifies a module for helloclient.
  8. Remove unwanted dependencies and files for helloclient.
    • Click the Files tab (next to Projects tab).
    • In the Files window, expand the src directory below helloclient, right-click the test directory and choose Delete.
    • In the Projects window, expand the TestLibraries node of helloclient, right-click on junit-3.8.1.jar, and select Remove Dependency.
    • Remove com.example.maven.jaxws.App.java from the SourcePackages directory.

Add JAX-WS JARs and Repositories

Now that you've created the project and its subprojects, you need to couple them with needed JAX-WS jar files and repositories.

  1. Add a dependency on jaxws-rt.jar.
    • Expand jaxws-maven-sample in the Projects window and right-click on Libraries.
    • Select "Add Library..." and then enter the following information in the Add Library popup window:
          - GroupId: com.sun.xml.ws
          - ArtifactId: jaxws-rt
          - Version: 2.1.3
          - Scope: compile (The scope determines if the artifact is required for compile time or runtime).
    • Click the OK button.

    Notice that the pom.xml file for jaxws-maven-sample now has a compile-time dependency on jaxws-rt.jar and specifies a scope of compile -- the jaxws-rt.jar file is required to be available for the service and client at runtime.
    GlassFish includes JAX-WS, so if you use GlassFish as the deployment container, you can set the Scope value to "provided". In this case, Maven creates a "skinny" WAR file, that is, it doesn't bundle the jax-ws jar files into the WAR.
  2. Add repository information for the JAX-WS JARs. Maven uses this information to get the jaxws-maven-plugin and its dependent artifacts.
    • Expand the Project Files node for jaxws-maven-sample and open the pom.xml file.
    • Add the following repository information for downloading JAX-WS JARs:
         <repositories>
           <repository>
             <id>maven-repository.dev.java.net</id>
             <name>Java.net Repository for Maven 1</name>
             <url>http://download.java.net/maven/1/</url>
             <layout>legacy</layout>
           </repository>
           <repository>
             <id>maven2-repository.dev.java.net</id>
             <name>Java.net Repository for Maven 2</name>
             <url>http://download.java.net/maven/2/</url>
           </repository>
         </repositories>

    This adds information for both the Maven 1 and Maven 2 repositories. (Some of the JAX-WS dependencies exist in both repositories.)
  3. Add plugin repository information for the jaxws-maven-plugin to the pom.xml file, as follows:
       <pluginRepositories>
         <pluginRepository>
           <id>maven2-repository.dev.java.net</id>
           <url>http://download.java.net/maven/2/</url>
         </pluginRepository>
       </pluginRepositories>
    Because all the configuration specifications are in the pom.xml file of the parent project, the configuration is shared by the subprojects helloservice and helloclient.

Build the Web Service

  1. Add logic to helloservice.
    • Right-click the SourcePackages node in the helloservice project.
    • Select New, then Java Class.
    • In the New Java Class window, specify:
          - Class Name: Hello
          - Package: com.example.maven.jaxws.helloservice
    • Click the Finish button.
    • Update the source code for the Hello class to annotate it as a WebService and include a method sayHello. The updated source code should look as follows:
         package com.example.maven.jaxws.helloservice;
         import javax.jws.WebService;
         @WebService
         public class Hello {
           public String sayHello(String param) {
             return "Hello " + param;
           }
         }
  2. Run the jaxws-maven-plugin:wsgen on the SEI class.
    • Open the pom.xml file of helloservice.
    • Add the following code under the build section in the pom.xml file:
            <plugins>     
              <plugin>
              <groupId>org.codehaus.mojo</groupId>
              <artifactId>jaxws-maven-plugin</artifactId>
                <executions>
                  <execution>
                    <goals>
                      <goal>wsgen</goal>
                    </goals>
                    <configuration>
                    <sei>com.example.maven.jaxws.helloservice.Hello
                    </sei>
                    <!--for demo purpose only, the webapp does not-->
                    <!--need the generated wsdl files-->
                    <genWsdl>true</genWsdl>          
                    <keep>true</keep>
                    </configuration>
                  </execution>
                </executions>
              </plugin>
            </plugins>

    As mentioned earlier, the jaxws-maven-plugin:wsgen goal is automatically invoked during the process-classes life cycle phase. The <sei> element value com.example.maven.jaxws.helloservice.Hello will be passed to the goal as a parameter.

Deploy the Web Service

  1. Specify deployment information.
    • If you use GlassFish or any other Java EE 5 container to deploy the web service, change the default web.xml file to use version "2.5". To do that:
          - Expand the Web Pages node in the helloservice project.
          - Expand the WEB-INF node and select the web.xml file.
          - Click the XML view button above the source editor window to view the XML contents of the file.
          - Replace the contents of the web.xml file with the following:
         <web–app version="2.5"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema–instance"
             xsi:schemaLocation=
             "http://java.sun.com/xml/ns/javaee
             http://java.sun.com/xml/ns/javaee/web–app_2_5.xsd">
           <welcome–file–list>
           <welcome–file>index.jsp</welcome–file>
           </welcome–file–list>
         </web–app>
      Make sure to remove the <!DOCTYPE> element at the beginning of the file.
          - Save the file.
  2. Deploy the artifacts to GlassFish.
    • Right-click the helloservice project and select Properties.
    • In the Run category, specify the following:
          - Server: GlassFish v2
          - Context Path: /helloservice
          - Click the OK button.
    You can also optionally check the Display Browser on Run checkbox and enter HelloService?wsdl in the Relative URL field. If you make these optional specifications, NetBeans will open a browser showing the helloservice WSDL after the helloservice service is deployed.
    In response, the pom.xml file for helloservice is updated to deploy the artifacts to GlassFish.

Run the Service

  • Right-Click on helloservice and select Run.
    NetBeans runs Maven to build the web application and automatically deploys the WAR file to GlassFish. You can see the process in the NetBeans Output window. You can access the WSDL for the service to check if the service is successfully deployed. If you checked the Display Browser on Run checkbox as described in previous step, NetBeans opens a browser showing the WSDL of the deployed web service. If you did not check the Display Browser on Run checkbox, you can display the WSDL for the web service by opening http://localhost:8080/helloservice/HelloService?wsdl in your browser.

Create a Client to Invoke the Web Service

  1. Run jaxws-maven-plugin:wsimport on the helloservice WSDL:
    • Open the pom.xml file of helloclient.
    • Add the following code to the pom.xml file:
         <build>
           <plugins>
             <plugin>
               <groupId>org.codehaus.mojo</groupId>
                 <artifactId>jaxws-maven-plugin</artifactId>
                 <executions>
                   <execution>
                     <goals>
                       <goal>wsimport</goal>
                     </goals>
                     <configuration>
                       <wsdlUrls>
                         <wsdlUrl>
               http://localhost:8080/helloservice/HelloService?wsdl
                         </wsdlUrl>
                       </wsdlUrls>
                   <packageName>com.example.maven.jaxws.helloclient
                   </packageName>
                     </configuration>
                   </execution>
                 </executions>
             </plugin>
           </plugins>
         <bulid>

    The jaxws-maven-plugin:wsimport goal is run during the life cycle phase generate-sources. As you can see in the above configuration, wsimport is run on the WSDL located at http://localhost:8080/helloservice/HelloService?wsdl to generate Java classes in the com.example.maven.jaxws.helloclient package.
  2. Build the client.
    • Right-click on the helloclient project and select build. Maven builds the project, runs wsimport, and generates all the Web Service artifacts that you see in the target folder. (To see the generated files, open then Files window and expand helloclient/target).
    • Expand the Source packages node in the helloclient project and right-click on com.example.maven.jaxws.helloclient
    • Select New, then Java class.
    • Specify the class name as HelloClient.
    • Click the Finish button.
    • Update the HelloClient class with the following source code:
         package com.example.maven.jaxws.helloclient;
         public class HelloClient {
           public static void main(String[] args) {
           HelloService service = new HelloService();
           Hello port= service.getHelloPort();
           System.out.println(port.sayHello("Duke"));
           }
         }
  3. Associate the NetBeans IDE action "Run" to build the jar and run HelloClient.
    • Right-click on helloclient and select Properties.
    • Under Run category, enter com.example.maven.jaxws.helloclient.HelloClient as the Main class.
    • Click the OK button.

Run the Client

  • Right click on helloclient and choose Run.
    Maven runs wsimport on the WSDL file, creates Java classes, compiles HelloClient, and runs it. In the NetBeans Output window you should see the following result of the web service invocation:
       Hello Duke

Summary

Using Maven you can easily create JAX-WS-based web services. Although this tip showed you how to do that using NetBeans, you can also can create JAX-WS-based web services using Maven manually, that is, without using NetBeans. To do so, use the mvn CLI and edit the pom files as needed. However, NetBeans makes it easier to use Maven for your projects and saves you from having to worry about configuration syntax.

For more information about using Maven to create JAX-WS-based web services, see the Metro User's Guide.

Friday, November 20, 2009

Configuring and Managing WebLogic JMS

Using WLST to Manage JMS Servers and JMS System Resources

The WebLogic Scripting Tool (WLST) is a command-line scripting interface that you can use to create and manage JMS servers and JMS system resources. See "Using the WebLogic Scripting Tool and WLST Sample Scripts in the WebLogic Scripting Tool.


Understanding System Modules and Subdeployments

A module is described by the jms-system-resource MBean in the config.xml file. Basic components of a jms-system-resource MBean are:

  • name—Name of the module.
  • target—Server, cluster, or migratable target the module is targeted to.
  • sub-deployment—A mechanism by which JMS module resources (such as queues, topics, and connection factories) are grouped and targeted to a server resource (such as a JMS server instance, WebLogic server instance, or cluster).
  • descriptor-file-name—Path and filename of the system module file.

The JMS resources of a module are located in a module descriptor file that conforms to the weblogic-jmsmd.xml schema. In Figure 6-1, the module is named myModule-jms.xml and it contains JMS resource definitions for a connection factory and a queue. The sub-deployment-name element is used to group and target JMS resources in the myModule-jms.xml file to targets in the config.xml. You have to provide a value for the sub-deployment-name element when using WLST. For more information on subdeployments, see "Targeting JMS Modules and Subdeployment Resources". In Figure 6-1, the sub-deployment-name DeployToJMSServer1is used to group and target the connection factory CConfac and the queue CQueue in the myModule-jms module.

For more information on how to use JMS resources, see "Understanding JMS Resource Configuration in Configuring and Managing WebLogic JMS.

Figure 6-1 Subdeployment Architecture

Subdeployment Architecture


How to Create JMS Servers and System Resources

Basic tasks you need to perform when creating JMS resources with the WLST are:

  • Start an edit session.
  • Create a JMS system module that includes JMS system resources, such as queues, topics, and connection factories.
  • Create JMS server resources.

After you have established an edit session, use the following steps configure JMS servers and system resources:

  1. Get the WebLogic Server MBean object for the server you want to configure resources. For example:
  2. servermb=getMBean("Servers/examplesServer")
        if servermb is None:
            print '@@@ No server MBean found'



  3. Create your system resource. For example:



  4. jmsMySystemResource = create(myJmsSystemResource,"JMSSystemResource")



  5. Target your system resource to a WebLogic Server instance. For example:



  6. jmsMySystemResource.addTarget(servermb)



  7. Get your system resource object. For example:



  8. theJMSResource = jmsMySystemResource.getJMSResource()



  9. Create resources for the module, such as queues, topics, and connection factories. For example:



  10. connfact1 = theJMSResource.createConnectionFactory(factoryName)




    jmsqueue1 = theJMSResource.createQueue(queueName)



  11. Configure resource attributes. For example:



  12. connfact1.setJNDIName(factoryName)
    jmsqueue1.setJNDIName(queueName)



  13. Create a subdeployment name for system resources . See Understanding System Modules and Subdeployments.For example:



  14. connfact1.setSubDeploymentName('DeployToJMSServer1')
    jmsqueue1.setSubDeploymentName('DeployToJMSServer1')



  15. Create a JMS server. For example:



  16. jmsserver1mb = create(jmsServerName,'JMSServer')



  17. Target your JMS server to a WebLogic Server instance. For example:



  18. jmsserver1mb.addTarget(servermb)



  19. Create a subdeployment object using the value you provided for the sub-deployment-name element. This step groups the system resources in module to a sub-deployment element in the config.xml. For example:



  20. subDep1mb = jmsMySystemResource.createSubDeployment('DeployToJMSServer1')



  21. Target the subdeployment to a server resource such as a JMS server instance, WebLogic Server instance, or cluster. For example:



  22. subDep1mb.addTarget(jmsserver1mb)




Listing 6-1 WLST Script to Create JMS Resources




"""
This script starts an edit session, creates a JMS Server,
targets the jms server to the server WLST is connected to and creates
a JMS System module with a jms queue and connection factory. The
jms queues and topics are targeted using sub-deployments.
"""

import sys
from java.lang import System

print "@@@ Starting the script ..."

myJmsSystemResource = "CapiQueue-jms"
factoryName = "CConFac"
jmsServerName = "myJMSServer"
queueName = "CQueue"

url = sys.argv[1]
usr = sys.argv[2]
password = sys.argv[3]

connect(usr,password, url)
edit()
startEdit()

//Step 1
servermb=getMBean("Servers/examplesServer")
    if servermb is None:
        print '@@@ No server MBean found'

else:




    //Step 2
    jmsMySystemResource = create(myJmsSystemResource,"JMSSystemResource")




    //Step 3
    jmsMySystemResource.addTarget(servermb)

    //Step 4
    theJMSResource = jmsMySystemResource.getJMSResource()

    //Step 5
    connfact1 = theJMSResource.createConnectionFactory(factoryName)
    jmsqueue1 = theJMSResource.createQueue(queueName)




    //Step 6
    connfact1.setJNDIName(factoryName)
    jmsqueue1.setJNDIName(queueName)





    //Step 7
    jmsqueue1.setSubDeploymentName('DeployToJMSServer1') 




    connfact1.setSubDeploymentName('DeployToJMSServer1')
    //Step 8
    jmsserver1mb = create(jmsServerName,'JMSServer')
    //Step 9
    jmsserver1mb.addTarget(servermb)

    //Step 10
    subDep1mb = jmsMySystemResource.createSubDeployment('DeployToJMSServer1')




    //Step 11
    subDep1mb.addTarget(jmsserver1mb)
.
.
.






How to Modify and Monitor JMS Servers and JMS Resources



You can modify or monitor JMS objects and attributes by using the appropriate method available from the MBean.




  • You can modify JMS objects and attributes using the set, target, untarget, and delete methods.


  • You can monitor JMS runtime objects using get methods.



For more information, see Navigating and Editing MBeans in the WebLogic Scripting Tool.





Listing 6-2 WLST Script to Modify JMS Objects




.
.
print '@@@ delete system resource'
jmsMySystemResource = delete("CapiQueue-jms","JMSSystemResource")
print '@@@ delete server'
jmsserver1mb = delete(jmsServerName,'JMSServer')
.
.
.






Best Practices when Using WLST to Configure JMS



This section provides best practices information when using WLST to configure JMS servers and resources:




  • Trap for Null MBean objects (such as servers, JMS servers, modules) before trying to manipulate the MBean object.


  • Use a meaningful name when providing a subdeployment name. For example, the subdeployment name DeployToJMSServer1 tells you that all subdeployments with this name are deployed to JMSServer1.


  • BEA provides sample scripts and utilities to configure WebLogic domain resources using WLST Offline and/or WLST Online. For more information, see the wlst Project Home.

Labels:

Wednesday, November 18, 2009

javax.xml.soap.SOAPFault is an interface, and JAXB can't handle interfaces

 

When your interface is implemented by a large number of sub-classes, consider using XmlRootElement annotation like this:

XmlRootElement for open-ended interfaces

@XmlRootElement
class Zoo {
  @XmlAnyElement
  public List<Animal> animals;
}
interface Animal {
  void sleep();
  void eat();
  ...
}
@XmlRootElement
class Dog implements Animal { ... }
@XmlRootElement
class Lion implements Animal { ... }


This will produce XML documents like this:



<zoo>
    <lion> ... </lion>
    <dog> ... </dog>
</zoo>


The key characteristics of this approach is:




  1. Implementations are open-ended; anyone can implement those interfaces, even by different people from different modules, provided they are all given to the JAXBContext.newInstance method. There's no need to list all the implementation classes in anywhere.


  2. Each implementation of the interface needs to have an unique element name.


  3. Every reference to interface needs to have the XmlElementRef annotation. The type=Object.class portion tells JAXB that the greatest common base type of all implementations would be java.lang.Object.



is often useful with this, as it allows you need to group them. Such as:



XmlRootElement for open-ended interfaces



@XmlRootElement
class Zoo {
  @XmlElementWrapper
  @XmlAnyElement
  public List<Animal> onExhibit;
  @XmlElementWrapper
  @XmlAnyElement
  public List<Animal> resting;
}

XML:

<zoo>
    <onExhibit>
        <lion> ... </lion>
        <dog> ... </dog>
    </onExhibit>
    <resting>
        <lion> ... </lion>
        <dog> ... </dog>
    </resting>
</zoo>


 



When you use interfaces just to hide your implementation classes from exposure, and when there's 1-to-1 (or close to 1-on-1) relationship between a class and an interface, XmlJavaTypeAdapter can be used like below.



XmlJavaTypeAdapter for interfaces



@XmlJavaTypeAdapter(FooImpl.Adapter.class)
interface IFoo {
  ...
}
class FooImpl implements IFoo {
  @XmlAttribute
  private String name;
  @XmlElement
  private int x;
  
  ...
  
  static class Adapter extends XmlAdapter<FooImpl,IFoo> {
    IFoo unmarshal(FooImpl v) { return v; }
    FooImpl marshal(IFoo v) { return (FooImpl)v; }
  }
}
class Somewhere {
  public IFoo lhs;
  public IFoo rhs;
}
XML:


<somewhere>
  <lhs name="...">
    <x>5</x>
  </lhs>
  <rhs name="...">
    <x>5</x>
  </rhs>
</somewhere>


 



The key characteristics of this approach is:




  1. Interface and implementation will be tightly coupled through an adapter, although changing an adapter code will allow you to support multiple implementations.


  2. There's no need of any annotation in where interfaces are used.



A variation of this technique is when you have a few implementations for interface, not just one.



XmlJavaTypeAdapter for interfaces with multiple implementations



@XmlJavaTypeAdapter(AbstractFooImpl.Adapter.class)
interface IFoo {
  ...
}
abstract class AbstractFooImpl implements IFoo {
  ...
  
  static class Adapter extends XmlAdapter<AbstractFooImpl,IFoo> {
    IFoo unmarshal(AbstractFooImpl v) { return v; }
    AbstractFooImpl marshal(IFoo v) { return (AbstractFooImpl)v; }
  }
}
class SomeFooImpl extends AbstractFooImpl {
  @XmlAttribute String name;
  ...
}
class AnotherFooImpl extends AbstractFooImpl {
  @XmlAttribute int id;
  ...
}
class Somewhere {
  public IFoo lhs;
  public IFoo rhs;
}


XML:



<somewhere>
  <lhs xsi:type="someFooImpl" name="...">
  </lhs>
  <rhs xsi:type="anotherFooImpl" id="3" />
</somewhere>


Note that SomeFooImpl and AnotherFooImpl must be submitted to JAXBContext.newInstance one way or the other.



To take this example a bit further, you can use Object instead of AbstractFooImpl. The following example illustarates this:



XmlJavaTypeAdapter for interfaces with multiple implementations



@XmlJavaTypeAdapter(AnyTypeAdapter.class)
interface IFoo {
  ...
}
public class AnyTypeAdapter extends XmlAdapter<Object,Object> {
  Object unmarshal(Object v) { return v; }
  Object marshal(Object v) { return v; }
}
class SomeFooImpl implements IFoo {
  @XmlAttribute String name;
  ...
}
class Somewhere {
  public IFoo lhs;
  public IFoo rhs;
}


Schema:


<xs:complexType name="somewhere">
  <xs:sequence>
    <xs:element name="lhs" type="xs:anyType" minOccurs="0"/>
    <xs:element name="rhs" type="xs:anyType" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>


As you can see, the schema will generated to accept xs:anyType which is more relaxed than what the Java code actually demands. The instance will be the same as the above example. Starting from JAXB RI 2.1, we bundle the com.sun.xml.bind.AnyTypeAdapter class in the runtime that defines this adapter. So you won't have to write this adapter in your code.



If the use of interface is very little and there's 1-to-1 (or close to) relationship between interfaces and implementations, then you might find XmlElement to be the least amount of work.



XmlElement for interfaces



interface IFoo {
  ...
}
class FooImpl implements IFoo {
  ...
}
class Somewhere {
  @XmlElement(type=FooImpl.class)
  public IFoo lhs;
}


XML:


<somewhere>
  <lhs> ... </lhs>
</somewhere>


This effectively tells JAXB runtime that "even though the field is IFoo, it's really just FooImpl.



In this approach, a reference to an interface has to have knowledge of the actual implementation class. So while this requires the least amount of typing, it probably wouldn't work very well if this crosses module boundaries.



Like the XmlJavaTypeAdapter approach, this can be used even when there are multiple implementations, provided that they share the common ancestor.



The extreme of this case is to specify @XmlElement(type=Object.class).

Labels: ,

Saturday, November 14, 2009

WebLogic Server Changing Classes in a Running Server

 

Changing Classes in a Running Program

WebLogic Server allows you to deploy newer versions of application modules such as EJBs while the server is running. This process is known as hot-deploy or hot-redeploy and is closely related to classloading.

Java classloaders do not have any standard mechanism to undeploy or unload a set of classes, nor can they load new versions of classes. In order to make updates to classes in a running virtual machine, the classloader that loaded the changed classes must be replaced with a new classloader. When a classloader is replaced, all classes that were loaded from that classloader (or any classloaders that are offspring of that classloader) must be reloaded. Any instances of these classes must be re-instantiated.

In WebLogic Server, each application has a hierarchy of classloaders that are offspring of the system classloader. These hierarchies allow applications or parts of applications to be individually reloaded without affecting the rest of the system. WebLogic Server Application Classloading discusses this topic.

How to use Quartz in web application

(copied from http://cake.wikidot.com/quartz )

General references

Home
http://www.opensymphony.com/quartz/

Wiki (Tutorial , Configuration, CookBook, …)
http://www.opensymphony.com/quartz/wikidocs/

Tutorial
http://www.onjava.com/pub/a/onjava/2005/09/28/what-is-quartz.html?page=1

Examples

 

Quartz version: 1.6.0
Java 1.6.0
Tomcat 5.5.25

jar files under the WEB-INF/lib

  • quartz-1.6.0.jar
  • log4j-1.2.11.jar
  • commons-beanutils.jar
  • commons-collections-3.1.jar
  • commons-digester-1.7.jar
  • commons-logging-api.jar
  • commons-logging.jar
  • jta.jar

QuartzInitializerServlet configuration

<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>
org.quartz.ee.servlet.QuartzInitializerServlet
</servlet-class>
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>


Copy the 3 following files under WEB-INF\classes



log4j.properties



# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=INFO, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n


 



quartz.properties




This sample is based on the examples of the Quartz distribution



#============================================================================
# Configure Main Scheduler Properties
#============================================================================

org.quartz.scheduler.instanceName = CakeNoteScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false

#============================================================================
# Configure ThreadPool
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 12
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

#org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.useProperties = false
#org.quartz.jobStore.dataSource = myDS
#org.quartz.jobStore.tablePrefix = QRTZ_
#org.quartz.jobStore.isClustered = false

#============================================================================
# Configure Datasources
#============================================================================

#org.quartz.dataSource.myDS.driver = org.postgresql.Driver
#org.quartz.dataSource.myDS.URL = jdbc:postgresql://localhost/dev
#org.quartz.dataSource.myDS.user = jhouse
#org.quartz.dataSource.myDS.password =
#org.quartz.dataSource.myDS.maxConnections = 5

#============================================================================
# JobInitializationPlugin (xml declarative way to trigger jobs)
#============================================================================

org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
#org.quartz.plugin.jobInitializer.fileName = quartz_jobs.xml
#org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
#org.quartz.plugin.jobInitializer.failOnFileNotFound = true


 



quartz_jobs.xml



<?xml version="1.0" encoding="UTF-8"?>
<quartz xmlns="http://www.opensymphony.com/quartz/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opensymphony.com/quartz/JobSchedulingData
http://www.opensymphony.com/quartz/xml/job_scheduling_data_1_5.xsd"
version="1.5" overwrite-existing-jobs="true">
<job>
<job-detail>
<name>testjob</name>
<group>CAKENOTE_GROUP</group>
<description>Basic test job</description>
<job-class>cakenote.quartz.job.TestJob</job-class>
<job-data-map allows-transient-data="false">
<entry>
<key>param1</key>
<value>value1</value>
</entry>
<entry>
<key>param2</key>
<value>value2</value>
</entry>
</job-data-map>
</job-detail>
<trigger>
<simple>
<name>my-trigger</name>
<group>MYTRIGGER_GROUP</group>
<job-name>testjob</job-name>
<job-group>CAKENOTE_GROUP</job-group>
<!-- repeat indefinitely every 5 seconds -->
<repeat-count>-1</repeat-count>
<repeat-interval>5000</repeat-interval>
</simple>
</trigger>
</job>
</quartz>


 



Create the following class



package cakenote.quartz.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class TestJob implements Job {

public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println(context.getJobDetail().getName());
}

}

Caused by: java.rmi.ConnectException: Bootstrap to 10.45.26.191/10.45.26.191:7001 failed. It is likely that the remote side declared peer gone on this JVM

 

The actual problem here is if you give the Listen Address (The IP address or DNS name this server uses to listen for incoming connections)

8.1  server----> Configuration---->general---->Listen Address: TAB if there is a DNS Name entered here then you will encounter this problem

10.2 Home >Summary of Servers >ADMIN  (Configuration TAB: Listen Address: )

Solution:

1. Please clear this text box and your problem would be resolved ......

2. if the server listen on the DNS name, then you can add the DNS name to you local hosts.

Java enum

Enums and Template Methods

Remember that the enum is basically a special class type, and can have methods and fields just like any other class. Remember also that each declared field is also an instance of the enum. So, applying the "Template Method" design pattern, one can create enumerations that are factories or command objects, but a defined set of objects. Here is a simple example of a "command" enumeration:

public enum Toy {
DOLL() {
@Override public void execute() {
System.out.println("I'm a doll.");
}
},
SOLDIER() {
@Override public void execute() {
System.out.println("I'm a soldier.");
}
};
//template method
public abstract void execute();
}


Another solution to seperate the implementation.


enum ToyEnum implements Toy
{
  DOLL(new Doll ()), SOLDIER(new Soldier ());
  final private Toy impl;
  private ToyEnum (Toy impl)
  {
    this.impl = impl;
  }
  //template method
  public void execute ()
  {
    impl.execute ();
  }
}
interface Toy
{
  public void execute ();
}
class Doll implements Toy
{
  public void execute ()
  {
    System.out.println ("I'm a doll.");
  }
}
class Soldier implements Toy
{
  public void execute ()
  {
    System.out.println ("I'm a soldier.");
  }
}


With the use of static imports, the client code calling this enumeration would look like:



SOLDIER.execute();
DOLL.execute();
//or better...
getToy().execute();


The resulting code is clear and self-documenting. Using this pattern is a great alternative in many cases to the more common if(toy=="soldier"){...} else if(toy=="doll"){...} else{...} logic since it is easier to read, extend, and maintain.



 



Reverse Lookups



Often in your object model it is common to have data that is naturally "associated" with an enumeration. Since an enum is a class, it is easy to represent this associated information as class fields. Often it is desirable to "lookup" the associated enumeration using the field value. This is easy to do using a static java.util.Map. Take, for example, a Status enum that has an associated status code.



public enum Status 
{
WAITING(0),
READY(1),
SKIPPED(-1),
COMPLETED(5);

private static final Map<Integer,Status> lookup
= new HashMap<Integer,Status>();

static {
for(Status s : EnumSet.allOf(Status.class))
lookup.put(s.getCode(), s);
}

private int code;

private Status(int code) {
this.code = code;
}

public int getCode() { return code; }

public static Status get(int code) {
return lookup.get(code);
}
}


The static get(int) method here provides the reverse lookup by simply getting the value from the Map. The static block to populate the Map uses a specialized implementation of Set, java.util.EnumSet, that "probably" (according to the javadocs) has better performance than java.util.HashSet. Java 5.0 also provides java.util.EnumMap, a specialized implementation of Map for enumerations that is more compact than java.util.HashMap.