Return-Path: Delivered-To: apmail-ws-axis-dev-archive@www.apache.org Received: (qmail 622 invoked from network); 2 Jan 2007 06:02:56 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 2 Jan 2007 06:02:55 -0000 Received: (qmail 7165 invoked by uid 500); 2 Jan 2007 06:03:01 -0000 Delivered-To: apmail-ws-axis-dev-archive@ws.apache.org Received: (qmail 7043 invoked by uid 500); 2 Jan 2007 06:03:01 -0000 Mailing-List: contact axis-cvs-help@ws.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list axis-cvs@ws.apache.org Received: (qmail 7032 invoked by uid 500); 2 Jan 2007 06:03:01 -0000 Delivered-To: apmail-ws-axis2-cvs@ws.apache.org Received: (qmail 7029 invoked by uid 99); 2 Jan 2007 06:03:01 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Jan 2007 22:03:01 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Jan 2007 22:02:51 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 865BC1A981A; Mon, 1 Jan 2007 22:01:55 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r491750 - /webservices/axis2/branches/java/1_1/xdocs/1_1/pojoguide.html Date: Tue, 02 Jan 2007 06:01:55 -0000 To: axis2-cvs@ws.apache.org From: chatra@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070102060155.865BC1A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: chatra Date: Mon Jan 1 22:01:54 2007 New Revision: 491750 URL: http://svn.apache.org/viewvc?view=rev&rev=491750 Log: corrected issue with pre tags. Now the bold fonts show after maven site build Modified: webservices/axis2/branches/java/1_1/xdocs/1_1/pojoguide.html Modified: webservices/axis2/branches/java/1_1/xdocs/1_1/pojoguide.html URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_1/xdocs/1_1/pojoguide.html?view=diff&rev=491750&r1=491749&r2=491750 ============================================================================== --- webservices/axis2/branches/java/1_1/xdocs/1_1/pojoguide.html (original) +++ webservices/axis2/branches/java/1_1/xdocs/1_1/pojoguide.html Mon Jan 1 22:01:54 2007 @@ -1,605 +1,605 @@ - - - - POJO Web Services using Axis2 - - - - -

POJO Web Services using Apache Axis2

- -

Want a quick way to get a Web service up and running in no time? Well -then, you should consider creating a Plain Old Java Object (POJO) to deploy -using Apache Axis2 on Apache Tomcat. POJOs are fast to build and easy to -maintain, meaning you'll save a lot of time building and debugging your code. -This document shows you how to take a simple POJO, and deploy it on Apache -Tomcat as a Web service in the exploded directory format. You'll also be -shown how to take a POJO based on the Spring Framework, and deploy that as an -AAR packaged Web service on Tomcat.

- -

Content

- - - -

Introduction

- -

The task of building a Web service can sometimes be overwhelming, but not -with POJOs! The old-school Plain Old Java Object is a simple and quick way to -get most, if not all, of your currently existing Java classes up on the Web -as readily accessible Web services. This document will show you how to build -a POJO-style Web service with Apache Axis2 and Tomcat, organized as -follows:

-
    -
  • The POJO: This is the Java class that you'll use throughout this - document
  • -
  • POJO deployment
  • -
  • Test the POJO Web service using an RPC based client
  • -
  • Limitations of straight POJO
  • -
  • Spring-based POJO Web service and deployment
  • -
- -

The code for the document can be found at Axis2_HOME/samples/pojoguide -& Axis2_HOME/samples/pojoguidespring once you extract the Axis2 Stadard -Distribution, and it might help to go grab it now to help you as you -follow along. Let's get started.

- - -

The POJO

- -

The POJO you'll be using throughout this document is a Weather service -POJO that consists of two classes: WeatherService and Weather. Weather -contains the Weather data: Temperature, forecast, rain (will it rain?), and -howMuchRain (See Code Listing 1).

- -

Code Listing 1: The Weather POJO

-
package sample.pojo.data;
-
-public class Weather{
-    float temperature;
-    String forecast;
-    boolean rain;
-    float howMuchRain;
-    
-    public void setTemperature(float temp){
-        temperature = temp;
-    }
-
-    public float getTemperature(){
-        return temperature;
-    }
-    
-    public void setForecast(String fore){
-        forecast = fore;
-    }
-
-    public String getForecast(){
-        return forecast;
-    }
-    
-    public void setRain(boolean r){
-        rain = r;
-    }
-
-    public boolean getRain(){
-        return rain;
-    }
-    
-    public void setHowMuchRain(float howMuch){
-        howMuchRain = howMuch;
-    }
-
-    public float getHowMuchRain(){
-        return howMuchRain;
-    }
-}
- -

And here's the WeatherService class, shown in Code Listing 2.

- -

Code Listing 2: The WeatherService class

-
package sample.pojo.service;
-
-import sample.pojo.data.Weather;
-
-public class WeatherService{
-    Weather weather;
-    
-    public void setWeather(Weather weather){
-        this.weather = weather;
-    }
-
-    public Weather getWeather(){
-        return this.weather;
-    }
-}
- -

Note that it's all just straight POJOs with field items and -getter and setter methods for each field. Next, -you'll take a look at what you need to do to make it ready for deployment on -Apache Axis2 and Tomcat.

- - -

POJO Web Service Using Apache Axis2 and Tomcat

- -

Got the POJOs? Great. This section will show you how to package them in -the exploded directory format for easy deployment. First you'll look at the -services.xml file that defines the Web service, and then you'll build the -files using Apache Ant, and deploy the -Web service on Tomcat.

- - -

Defining the Service: services.xml

- -

Before Axis2 can understand what is going on, you have to tell it to use -the services.xml file. Let's get right into it (see Code Listing 3).

- -

Code Listing 3: The service definition file: services.xml

-
<service name="WeatherService" scope="application">
-    <description>
-        Weather POJO Service
-    </description>
-    <messageReceivers>
-        <messageReceiver 
-            mep="http://www.w3.org/2004/08/wsdl/in-only"
-    class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
-        <messageReceiver
-            mep="http://www.w3.org/2004/08/wsdl/in-out"
-    class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
-    </messageReceivers>
-    <parameter name="ServiceClass">
-        sample.pojo.service.WeatherService
-    </parameter>
-</service>
- -

The name of the service is specified as WeatherService and the scope of -the service is application. As you can see in the WeatherService POJO, there -are two methods, an IN-ONLY method and a IN-OUT method, hence the ordering -for the messageReceiver elements within the messageReceivers tag. Lastly, the -ServiceClass parameter specifies the class of the Web service, which is -sample.pojo.service.WeatherService. When operations of your Web service get -called, the methods of the WeatherService class will be called. Next you'll -take a look at an easy method of building your application using Ant.

- - -

Building the POJO Web Service Using Apache Ant

- -

Ant is a slick build tool. It helps -reduce time to build applications, and several of the Axis2 command-line -tools create build.xml files for you, so that's why we'll use it here. We -won't go into the build.xml file that you'll be using in too much detail, so -here are the main Ant tasks you'll be using:

-
    -
  • generate.service -- This Ant task builds all the service relevant - source and copies the files to build/WeatherService
  • -
  • rpc.client -- This task builds the client relevant files, builds a JAR - at build/lib/rpc-client.jar, and then runs the client
  • -
- -

Before you can build the source, however, you'll need to download the -Axis2 1.1.1-bin and 1.1.1-war distributions here. Then modify the following -line inside the build.xml file (in the Axis2_HOME/samples/pojoguide directory -in the extracted Axis2 1.1.1 Standard Binary (bin) Distribution) :

-
<property name="axis2.home" value="c:\apps\axis2" />
- -

This modification contains the path to the root of the unzipped Axis2 -1.1.1-bin download. With -that explanation, you'll now build the source by typing the following: ant

- -

The following directory format should now exist at -build/WeatherService:

-
 - WeatherService
-   - META-INF
-     - services.xml
-   - sample
-     - pojo
-       - data
-         - Weather.class
-       - service
-         - WeatherService.class
- -

Simple isn't it? An excellent way to dive into Web services -development.

- -

Now get a Tomcat distribution (I -used v5.5), and start it up by running bin/startup.bat or -bin/startup.sh. Once it's running, deploy the Axis2 1.1.1-war by -copying the axis2.war file to Tomcat's webapps directory. Tomcat will proceed -by deploying axis2 and un-archive it into the webapps directory. Now copy the -WeatherService directory created when building our project to: -<tomcat-home>/webapps/axis2/WEB-INF/services.

- -

The service should quickly deploy, and you'll test the Web service using -the RPCServiceClient in the next section.

- - -

Testing the POJO Web Service Using RPCServiceClient

- -

OK, so the Web service should be running on Tomcat. Now you'll build a -simple RPCServiceClient and test the POJO Web service. You'll first start out -with the class constructs, creating the RPCServiceClient and initializing the -values of the Weather class within the Web service (See Code Listing 4).

- -

Code Listing 4: Setting the weather

-
package sample.pojo.rpcclient;
-
-import javax.xml.namespace.QName;
-
-import org.apache.axis2.AxisFault;
-import org.apache.axis2.addressing.EndpointReference;
-import org.apache.axis2.client.Options;
-import org.apache.axis2.rpc.client.RPCServiceClient;
-
-import sample.pojo.data.Weather;
-
-
-public class WeatherRPCClient {
-
-    public static void main(String[] args1) throws AxisFault {
-
-        RPCServiceClient serviceClient = new RPCServiceClient();
-
-        Options options = serviceClient.getOptions();
-
-        EndpointReference targetEPR = new EndpointReference(
-                "http://localhost:8080/axis2/services/WeatherService");
-        options.setTo(targetEPR);
-
-        // Setting the weather
-        QName opSetWeather =
-            new QName("http://service.pojo.sample/xsd", "setWeather");
-
-        Weather w = new Weather();
-
-        w.setTemperature((float)39.3);
-        w.setForecast("Cloudy with showers");
-        w.setRain(true);
-        w.setHowMuchRain((float)4.5);
-
-        Object[] opSetWeatherArgs = new Object[] { w };
-
-        serviceClient.invokeRobust(opSetWeather, opSetWeatherArgs);
-...
- -

The most interesting code to note is in bold font. Notice the targetEPR -variable you create, setting the endpoint reference to -http://localhost:8080/axis2/services/WeatherService. This is where you -deployed it on Axis2. You can also verify this by asking Axis2 to list its -services by going to the following URL: -http://localhost:8080/axis2/services/listServices.

- -

Next the opSetWeather variable gets setup, pointing to the setWeather -operation. Then the Weather data gets created and initialized. Lastly, you -invoke the Web service, which initializes the weather data (you'll verify -this soon). Next you get back the weather data (see Code Listing 5).

- -

Code Listing 5: Getting the weather data

-
...
-        serviceClient.invokeRobust(opSetWeather, opSetWeatherArgs);
-
-        // Getting the weather
-        QName opGetWeather =
-            new QName("http://service.pojo.sample/xsd", "getWeather");
-
-        Object[] opGetWeatherArgs = new Object[] { };
-        Class[] returnTypes = new Class[] { Weather.class };
-        
-        Object[] response = serviceClient.invokeBlocking(opGetWeather,
-                opGetWeatherArgs, returnTypes);
-        
-        Weather result = (Weather) response[0];
-        
-        if (result == null) {
-            System.out.println("Weather didn't initialize!");
-            return;
-        }
-...
- -

First you set the operation in opGetWeather to getWeather. Then you create -an empty argument list. Note this time you expect something back from the Web -service, and so you create a list of return types. Then you invoke the Web -service using a blocking call and wait for the weather data to be returned to -you, and you place it in the result variable. Lastly, you make sure it isn't -null and that it was successfully initialized by the previous call to -setWeather. Now display the data to verify that it is indeed what you set it -to (see Code Listing 6).

- -

Code Listing 6: Displaying the data

-
...
-            return;
-        }
-
-        // Displaying the result
-        System.out.println("Temperature               : " +
-                           result.getTemperature());
-        System.out.println("Forecast                  : " +
-                           result.getForecast());
-        System.out.println("Rain                      : " +
-                           result.getRain());
-        System.out.println("How much rain (in inches) : " +
-                           result.getHowMuchRain());
-        
-    }
-}
- -

You should receive the data shown in Code Listing 7.

- -

Code Listing 7: Output from running the client

-
rpc.client.run:
-     [java] Temperature               : 39.3
-     [java] Forecast                  : Cloudy with showers
-     [java] Rain                      : true
-     [java] How much rain (in inches) : 4.5
- -

Excellent, you have a working POJO Web service! Next you'll quickly morph -this one into a Spring based POJO.

- - -

Limitations and Strengths of POJO

- -

We've covered the strengths of using POJO based Web services, but what -about any limitations? One main limitation of POJO based Web services is the -lack of initialization support (meaning that you have to go into your Web -service and initialize the values before the Web service is completely -useful), but you'll soon see how to overcome that limitation with a Spring -based POJO, covered next.

- - -

Spring-based POJO Web Service

- -

Spring is a hot framework for J2EE and makes bean usage a breeze. You'll -use it in this section to create a Spring based POJO Web service. For this -section you'll need the spring.jar from the latest 1.x Spring download.

- - - -

Quick Introduction

- -

If you take a look at the source code of this document in -Axis2_HOME/samples/pojoguidespring (to see how the Spring based POJO Web -service is coded), you can see that the Weather class didn't change at all -and the WeatherService class only got its name changed to -WeatherSpringService.

- -

You'll also notice an applicationContext.xml file, which we'll cover -later: it's used to setup the beans used in our Web service.

- -

Now you might wonder what the SpringInit.java class is for: This service -is necessary, however, to initialize the Spring Framework's application -context.

- -

The client is pretty much the same, except you won't use it to initialize -the Weather data in the Web service, since Spring does that for you using -Inversion of Control (IoC), which is covered next.

- - -

The Service Definition: services.xml

- -

Because the core POJOs didn't change, you'll move straight to the -services.xml file. It's a bit longer this time because it instantiates two -services in one file (see Code Listing 7).

- -

Code Listing 7: Defining the services: services.xml

-
<serviceGroup>
-  <service name="SpringInit" 
-class="sample.spring.service.SpringInit">
-    <description>
-      This web service initializes Spring.
-    </description>
-    <parameter name="ServiceClass">
-        sample.spring.service.SpringInit
-    </parameter>
-    <parameter name="ServiceTCCL">composite</parameter>
-    <parameter name="load-on-startup">true</parameter>
-    <operation name="springInit">
-      <messageReceiver 
-      class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
-    </operation>
-  </service>
-  <service name="WeatherSpringService">
-    <description>
-      Weather Spring POJO Axis2 AAR deployment
-    </description>
-    <parameter name="ServiceClass">
-        sample.spring.service.WeatherSpringService
-    </parameter>
-    <parameter name="ServiceObjectSupplier">
-org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
-    </parameter>
-    <parameter name="SpringBeanName">
-        weatherSpringService
-    </parameter>
-    <messageReceivers>
-      <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
-      class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
-      <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
-      class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
-    </messageReceivers>
-  </service>
-</serviceGroup>
- -

You'll see a few familiar items in the above listing, and several changes. -Once again, the items in bold are most important. The ServiceTCCL property -under the SpringInit service makes sure that the Spring class loader is used -for the Web service, allowing it to properly instantiate the Spring -application context. The load-on-startup variable is a must-have so that the -service loads up immediately on startup, creating the Spring application -context. The WeatherSpringService stays mostly the same to the WeatherService -previously with a couple additions: The ServiceObjectSupplier provides the -service with the Spring application context, making it "Spring Aware."

- -

Lastly, the SpringBeanName points to the name of the bean associated with -this Web service, which is defined in the applicationContext.xml file -(essentially the WeatherSpringService). We'll cover the -applicationContext.xml file next. The application context: -applicationContext.xml file tells the Spring Framework, what beans are -defined. For this example, you'll define three of them (see Code Listing -8).

- -

Code Listing 8: Defining the application context: -applicationContext.xml

-
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
-"http://www.springframework.org/dtd/spring-beans.dtd">
-
-<beans>
-  <bean id="applicationContext" class=
-"org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
-
-  <bean id="weatherSpringService" 
-        class="sample.spring.service.WeatherSpringService">
-    <property name="weather" ref="weatherBean"/>
-  </bean>
-
-  <bean id="weatherBean" class="sample.spring.bean.Weather">
-    <property name="temperature" value="89.9"/>
-    <property name="forecast" value="Sunny"/>
-    <property name="rain" value="false"/>
-    <property name="howMuchRain" value="0.2"/>
-  </bean>
-</beans>
- -

The first one is Axis2's hook into Spring's application context (needed -since AAR deployment is quite different from regular WAR deployment). Next, -you define the bean pointed to by the services.xml file, the -weatherSpringService bean that points to the WeatherSpringService class. It -has one field property that gets initialized by the Spring Framework, -weather, which will be set to the weatherBean. The weatherBean is an -instantiation of the Weather class that holds information on the weather. -Spring will initialize it to the values shown above, and set the Weather -object in the WeatherSpringService class to this weatherBean instantiation. -Thus, when you deploy the Web service you won't have to instantiate the -values because they'll already be set.

- -

Next up is the SpringInit class.

- - -

Initializing the Spring application context: SpringInit

- -

Without the Spring application context being initialized quickly, you'll -run into problems. The SpringInit class initializes the Spring application -context on startup because it is a ServiceLifeCycle class, whose startUp -method gets called upon loading the class (and because its load-on-startup -property is set in the serices.xml file). The only code worth mentioning in -this class is shown in Code Listing 9.

- -

Code Listing 9: SpringInit's startUp method

-
    public void startUp(ConfigurationContext ignore,
-                        AxisService service) {
-        ClassLoader classLoader = service.getClassLoader();
-        ClassPathXmlApplicationContext appCtx = new
-            ClassPathXmlApplicationContext(new String[]
-                                           {"applicationContext.xml"}, 
-                                           false);
-        appCtx.setClassLoader(classLoader);
-        appCtx.refresh();
-        if (logger.isDebugEnabled()) {
-            logger.debug("\n\nstartUp() set spring classloader " +
-                         "via axisService.getClassLoader() ... ");
-        }
-    }
- -

Note that this method retrieves the Spring class loader, creates an -application context with applicationContext.xml as the parameters. This new -application context then gets the Spring class loader as its class loader. -The Spring Framework is now up and ready for our WeatherSpringService.

- -

Build and Deploy Using Apache Axis2 and Tomcat

- -

Great, your POJO is now ready for primetime within the Spring Framework. -Before you build, you'll first need to make sure the axis2-spring-1.1.1.jar and -spring.jar files are in the project's Axis2_HOME/lib directory.

- -

Note: The service will not deploy if you add the above jars files to the service archive due to cloass loding issues.

-

Now build the source and create an AAR file by typing: -ant

- -

It'll be created at target/WeatherSpringService.aar. Copy it over -to <tomcat-home>/webapps/axis2/WEB-INF/services, and Axis2 -should deploy it quickly.

- -

Next test the Web service to see if Spring really will initialize the -weather data for you.

- - -

Testing Using an RPCServiceClient

- -

It's as simple as it was for the other Web service, except this time type: -ant rpc.client

- -

Feel free to browse the code for this client in -src/client/WeatherSpringRPCClient.java. Essentially, this client does the -exact same thing as the client testing the WeatherService, except this one -skips the "Setting the weather" task since the weather data should already -have been set by the Spring framework at startup.

- -

Thus, you should get the following as output from the client:

-
run.client:
-    [javac] Compiling 1 source file to C:\axis2-1.1.1\samples\pojoguidespring\build\cl
-asses
-     [java] Temperature               : 89.9
-     [java] Forecast                  : Sunny
-     [java] Rain                      : false
-     [java] How much rain (in inches) : 0.2
- -

Which is exactly the values you set them to be in the -applicationContext.xml file!

- - -

Summary

- -

Apache Axis2 is an excellent way to expose your POJOs as Web services, and -Spring adds greater flexibility to your POJOs by adding beans support and -initialization abilities, along with all the other goodies provided by the -Spring framework.

- - -

For Further Study

- -

Apache Axis2-http://ws.apache.org/axis2/

- -

Axis2 Architecture-http://ws.apache.org/axis2/1_0/Axis2ArchitectureGuide.html

- -

Introduction to Apache Axis2-http://www.redhat.com/magazine/021jul06/features/apache_axis2/

- -

Working With Apache Axis2-http://www.wso2.net/articles/axis2/java/2006/09/13/working-with-axis2

- -

Apache Tomcat-http://tomcat.apache.org

- -

Spring Framework-http://www.springframework.org/

- - + + + + POJO Web Services using Axis2 + + + + +

POJO Web Services using Apache Axis2

+ +

Want a quick way to get a Web service up and running in no time? Well +then, you should consider creating a Plain Old Java Object (POJO) to deploy +using Apache Axis2 on Apache Tomcat. POJOs are fast to build and easy to +maintain, meaning you'll save a lot of time building and debugging your code. +This document shows you how to take a simple POJO, and deploy it on Apache +Tomcat as a Web service in the exploded directory format. You'll also be +shown how to take a POJO based on the Spring Framework, and deploy that as an +AAR packaged Web service on Tomcat.

+ +

Content

+ + + +

Introduction

+ +

The task of building a Web service can sometimes be overwhelming, but not +with POJOs! The old-school Plain Old Java Object is a simple and quick way to +get most, if not all, of your currently existing Java classes up on the Web +as readily accessible Web services. This document will show you how to build +a POJO-style Web service with Apache Axis2 and Tomcat, organized as +follows:

+
    +
  • The POJO: This is the Java class that you'll use throughout this + document
  • +
  • POJO deployment
  • +
  • Test the POJO Web service using an RPC based client
  • +
  • Limitations of straight POJO
  • +
  • Spring-based POJO Web service and deployment
  • +
+ +

The code for the document can be found at Axis2_HOME/samples/pojoguide +& Axis2_HOME/samples/pojoguidespring once you extract the Axis2 Stadard +Distribution, and it might help to go grab it now to help you as you +follow along. Let's get started.

+ + +

The POJO

+ +

The POJO you'll be using throughout this document is a Weather service +POJO that consists of two classes: WeatherService and Weather. Weather +contains the Weather data: Temperature, forecast, rain (will it rain?), and +howMuchRain (See Code Listing 1).

+ +

Code Listing 1: The Weather POJO

+
package sample.pojo.data;
+
+public class Weather{
+    float temperature;
+    String forecast;
+    boolean rain;
+    float howMuchRain;
+    
+    public void setTemperature(float temp){
+        temperature = temp;
+    }
+
+    public float getTemperature(){
+        return temperature;
+    }
+    
+    public void setForecast(String fore){
+        forecast = fore;
+    }
+
+    public String getForecast(){
+        return forecast;
+    }
+    
+    public void setRain(boolean r){
+        rain = r;
+    }
+
+    public boolean getRain(){
+        return rain;
+    }
+    
+    public void setHowMuchRain(float howMuch){
+        howMuchRain = howMuch;
+    }
+
+    public float getHowMuchRain(){
+        return howMuchRain;
+    }
+}
+ +

And here's the WeatherService class, shown in Code Listing 2.

+ +

Code Listing 2: The WeatherService class

+
package sample.pojo.service;
+
+import sample.pojo.data.Weather;
+
+public class WeatherService{
+    Weather weather;
+    
+    public void setWeather(Weather weather){
+        this.weather = weather;
+    }
+
+    public Weather getWeather(){
+        return this.weather;
+    }
+}
+ +

Note that it's all just straight POJOs with field items and +getter and setter methods for each field. Next, +you'll take a look at what you need to do to make it ready for deployment on +Apache Axis2 and Tomcat.

+ + +

POJO Web Service Using Apache Axis2 and Tomcat

+ +

Got the POJOs? Great. This section will show you how to package them in +the exploded directory format for easy deployment. First you'll look at the +services.xml file that defines the Web service, and then you'll build the +files using Apache Ant, and deploy the +Web service on Tomcat.

+ + +

Defining the Service: services.xml

+ +

Before Axis2 can understand what is going on, you have to tell it to use +the services.xml file. Let's get right into it (see Code Listing 3).

+ +

Code Listing 3: The service definition file: services.xml

+
<service name="WeatherService" scope="application">
+    <description>
+        Weather POJO Service
+    </description>
+    <messageReceivers>
+        <messageReceiver 
+            mep="http://www.w3.org/2004/08/wsdl/in-only"
+    class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
+        <messageReceiver
+            mep="http://www.w3.org/2004/08/wsdl/in-out"
+    class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
+    </messageReceivers>
+    <parameter name="ServiceClass">
+        sample.pojo.service.WeatherService
+    </parameter>
+</service>
+ +

The name of the service is specified as WeatherService and the scope of +the service is application. As you can see in the WeatherService POJO, there +are two methods, an IN-ONLY method and a IN-OUT method, hence the ordering +for the messageReceiver elements within the messageReceivers tag. Lastly, the +ServiceClass parameter specifies the class of the Web service, which is +sample.pojo.service.WeatherService. When operations of your Web service get +called, the methods of the WeatherService class will be called. Next you'll +take a look at an easy method of building your application using Ant.

+ + +

Building the POJO Web Service Using Apache Ant

+ +

Ant is a slick build tool. It helps +reduce time to build applications, and several of the Axis2 command-line +tools create build.xml files for you, so that's why we'll use it here. We +won't go into the build.xml file that you'll be using in too much detail, so +here are the main Ant tasks you'll be using:

+
    +
  • generate.service -- This Ant task builds all the service relevant + source and copies the files to build/WeatherService
  • +
  • rpc.client -- This task builds the client relevant files, builds a JAR + at build/lib/rpc-client.jar, and then runs the client
  • +
+ +

Before you can build the source, however, you'll need to download the +Axis2 1.1.1-bin and 1.1.1-war distributions here. Then modify the following +line inside the build.xml file (in the Axis2_HOME/samples/pojoguide directory +in the extracted Axis2 1.1.1 Standard Binary (bin) Distribution) :

+
<property name="axis2.home" value="c:\apps\axis2" />
+ +

This modification contains the path to the root of the unzipped Axis2 +1.1.1-bin download. With +that explanation, you'll now build the source by typing the following: ant

+ +

The following directory format should now exist at +build/WeatherService:

+
 - WeatherService
+   - META-INF
+     - services.xml
+   - sample
+     - pojo
+       - data
+         - Weather.class
+       - service
+         - WeatherService.class
+ +

Simple isn't it? An excellent way to dive into Web services +development.

+ +

Now get a Tomcat distribution (I +used v5.5), and start it up by running bin/startup.bat or +bin/startup.sh. Once it's running, deploy the Axis2 1.1.1-war by +copying the axis2.war file to Tomcat's webapps directory. Tomcat will proceed +by deploying axis2 and un-archive it into the webapps directory. Now copy the +WeatherService directory created when building our project to: +<tomcat-home>/webapps/axis2/WEB-INF/services.

+ +

The service should quickly deploy, and you'll test the Web service using +the RPCServiceClient in the next section.

+ + +

Testing the POJO Web Service Using RPCServiceClient

+ +

OK, so the Web service should be running on Tomcat. Now you'll build a +simple RPCServiceClient and test the POJO Web service. You'll first start out +with the class constructs, creating the RPCServiceClient and initializing the +values of the Weather class within the Web service (See Code Listing 4).

+ +

Code Listing 4: Setting the weather

+

package sample.pojo.rpcclient;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.addressing.EndpointReference;
+import org.apache.axis2.client.Options;
+import org.apache.axis2.rpc.client.RPCServiceClient;
+
+import sample.pojo.data.Weather;
+
+
+public class WeatherRPCClient {
+
+    public static void main(String[] args1) throws AxisFault {
+
+        RPCServiceClient serviceClient = new RPCServiceClient();
+
+        Options options = serviceClient.getOptions();
+
+        EndpointReference targetEPR = new EndpointReference(
+                "http://localhost:8080/axis2/services/WeatherService");
+        options.setTo(targetEPR);
+
+        // Setting the weather
+        QName opSetWeather =
+            new QName("http://service.pojo.sample/xsd", "setWeather");
+
+        Weather w = new Weather();
+
+        w.setTemperature((float)39.3);
+        w.setForecast("Cloudy with showers");
+        w.setRain(true);
+        w.setHowMuchRain((float)4.5);
+
+        Object[] opSetWeatherArgs = new Object[] { w };
+
+        serviceClient.invokeRobust(opSetWeather, opSetWeatherArgs);
+...

+ +

The most interesting code to note is in bold font. Notice the targetEPR +variable you create, setting the endpoint reference to +http://localhost:8080/axis2/services/WeatherService. This is where you +deployed it on Axis2. You can also verify this by asking Axis2 to list its +services by going to the following URL: +http://localhost:8080/axis2/services/listServices.

+ +

Next the opSetWeather variable gets setup, pointing to the setWeather +operation. Then the Weather data gets created and initialized. Lastly, you +invoke the Web service, which initializes the weather data (you'll verify +this soon). Next you get back the weather data (see Code Listing 5).

+ +

Code Listing 5: Getting the weather data

+

...
+        serviceClient.invokeRobust(opSetWeather, opSetWeatherArgs);
+
+        // Getting the weather
+        QName opGetWeather =
+            new QName("http://service.pojo.sample/xsd", "getWeather");
+
+        Object[] opGetWeatherArgs = new Object[] { };
+        Class[] returnTypes = new Class[] { Weather.class };
+        
+        Object[] response = serviceClient.invokeBlocking(opGetWeather,
+                opGetWeatherArgs, returnTypes);
+        
+        Weather result = (Weather) response[0];
+        
+        if (result == null) {
+            System.out.println("Weather didn't initialize!");
+            return;
+        }
+...

+ +

First you set the operation in opGetWeather to getWeather. Then you create +an empty argument list. Note this time you expect something back from the Web +service, and so you create a list of return types. Then you invoke the Web +service using a blocking call and wait for the weather data to be returned to +you, and you place it in the result variable. Lastly, you make sure it isn't +null and that it was successfully initialized by the previous call to +setWeather. Now display the data to verify that it is indeed what you set it +to (see Code Listing 6).

+ +

Code Listing 6: Displaying the data

+

...
+            return;
+        }
+
+        // Displaying the result
+        System.out.println("Temperature               : " +
+                           result.getTemperature());
+        System.out.println("Forecast                  : " +
+                           result.getForecast());
+        System.out.println("Rain                      : " +
+                           result.getRain());
+        System.out.println("How much rain (in inches) : " +
+                           result.getHowMuchRain());
+        
+    }
+}

+ +

You should receive the data shown in Code Listing 7.

+ +

Code Listing 7: Output from running the client

+
rpc.client.run:
+     [java] Temperature               : 39.3
+     [java] Forecast                  : Cloudy with showers
+     [java] Rain                      : true
+     [java] How much rain (in inches) : 4.5
+ +

Excellent, you have a working POJO Web service! Next you'll quickly morph +this one into a Spring based POJO.

+ + +

Limitations and Strengths of POJO

+ +

We've covered the strengths of using POJO based Web services, but what +about any limitations? One main limitation of POJO based Web services is the +lack of initialization support (meaning that you have to go into your Web +service and initialize the values before the Web service is completely +useful), but you'll soon see how to overcome that limitation with a Spring +based POJO, covered next.

+ + +

Spring-based POJO Web Service

+ +

Spring is a hot framework for J2EE and makes bean usage a breeze. You'll +use it in this section to create a Spring based POJO Web service. For this +section you'll need the spring.jar from the latest 1.x Spring download.

+ + + +

Quick Introduction

+ +

If you take a look at the source code of this document in +Axis2_HOME/samples/pojoguidespring (to see how the Spring based POJO Web +service is coded), you can see that the Weather class didn't change at all +and the WeatherService class only got its name changed to +WeatherSpringService.

+ +

You'll also notice an applicationContext.xml file, which we'll cover +later: it's used to setup the beans used in our Web service.

+ +

Now you might wonder what the SpringInit.java class is for: This service +is necessary, however, to initialize the Spring Framework's application +context.

+ +

The client is pretty much the same, except you won't use it to initialize +the Weather data in the Web service, since Spring does that for you using +Inversion of Control (IoC), which is covered next.

+ + +

The Service Definition: services.xml

+ +

Because the core POJOs didn't change, you'll move straight to the +services.xml file. It's a bit longer this time because it instantiates two +services in one file (see Code Listing 7).

+ +

Code Listing 7: Defining the services: services.xml

+

<serviceGroup>
+  <service name="SpringInit" 
+class="sample.spring.service.SpringInit">
+    <description>
+      This web service initializes Spring.
+    </description>
+    <parameter name="ServiceClass">
+        sample.spring.service.SpringInit
+    </parameter>
+    <parameter name="ServiceTCCL">composite</parameter>
+    <parameter name="load-on-startup">true</parameter>
+    <operation name="springInit">
+      <messageReceiver 
+      class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
+    </operation>
+  </service>
+  <service name="WeatherSpringService">
+    <description>
+      Weather Spring POJO Axis2 AAR deployment
+    </description>
+    <parameter name="ServiceClass">
+        sample.spring.service.WeatherSpringService
+    </parameter>
+    <parameter name="ServiceObjectSupplier">
+org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
+    </parameter>
+    <parameter name="SpringBeanName">
+        weatherSpringService
+    </parameter>
+    <messageReceivers>
+      <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
+      class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
+      <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
+      class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
+    </messageReceivers>
+  </service>
+</serviceGroup>

+ +

You'll see a few familiar items in the above listing, and several changes. +Once again, the items in bold are most important. The ServiceTCCL property +under the SpringInit service makes sure that the Spring class loader is used +for the Web service, allowing it to properly instantiate the Spring +application context. The load-on-startup variable is a must-have so that the +service loads up immediately on startup, creating the Spring application +context. The WeatherSpringService stays mostly the same to the WeatherService +previously with a couple additions: The ServiceObjectSupplier provides the +service with the Spring application context, making it "Spring Aware."

+ +

Lastly, the SpringBeanName points to the name of the bean associated with +this Web service, which is defined in the applicationContext.xml file +(essentially the WeatherSpringService). We'll cover the +applicationContext.xml file next. The application context: +applicationContext.xml file tells the Spring Framework, what beans are +defined. For this example, you'll define three of them (see Code Listing +8).

+ +

Code Listing 8: Defining the application context: +applicationContext.xml

+

<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
+"http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans>
+  <bean id="applicationContext" class=
+"org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
+
+  <bean id="weatherSpringService" 
+        class="sample.spring.service.WeatherSpringService">
+    <property name="weather" ref="weatherBean"/>
+  </bean>
+
+  <bean id="weatherBean" class="sample.spring.bean.Weather">
+    <property name="temperature" value="89.9"/>
+    <property name="forecast" value="Sunny"/>
+    <property name="rain" value="false"/>
+    <property name="howMuchRain" value="0.2"/>
+  </bean>
+</beans>

+ +

The first one is Axis2's hook into Spring's application context (needed +since AAR deployment is quite different from regular WAR deployment). Next, +you define the bean pointed to by the services.xml file, the +weatherSpringService bean that points to the WeatherSpringService class. It +has one field property that gets initialized by the Spring Framework, +weather, which will be set to the weatherBean. The weatherBean is an +instantiation of the Weather class that holds information on the weather. +Spring will initialize it to the values shown above, and set the Weather +object in the WeatherSpringService class to this weatherBean instantiation. +Thus, when you deploy the Web service you won't have to instantiate the +values because they'll already be set.

+ +

Next up is the SpringInit class.

+ + +

Initializing the Spring application context: SpringInit

+ +

Without the Spring application context being initialized quickly, you'll +run into problems. The SpringInit class initializes the Spring application +context on startup because it is a ServiceLifeCycle class, whose startUp +method gets called upon loading the class (and because its load-on-startup +property is set in the serices.xml file). The only code worth mentioning in +this class is shown in Code Listing 9.

+ +

Code Listing 9: SpringInit's startUp method

+

    public void startUp(ConfigurationContext ignore,
+                        AxisService service) {
+        ClassLoader classLoader = service.getClassLoader();
+        ClassPathXmlApplicationContext appCtx = new
+            ClassPathXmlApplicationContext(new String[]
+                                           {"applicationContext.xml"}, 
+                                           false);
+        appCtx.setClassLoader(classLoader);
+        appCtx.refresh();
+        if (logger.isDebugEnabled()) {
+            logger.debug("\n\nstartUp() set spring classloader " +
+                         "via axisService.getClassLoader() ... ");
+        }
+    }

+ +

Note that this method retrieves the Spring class loader, creates an +application context with applicationContext.xml as the parameters. This new +application context then gets the Spring class loader as its class loader. +The Spring Framework is now up and ready for our WeatherSpringService.

+ +

Build and Deploy Using Apache Axis2 and Tomcat

+ +

Great, your POJO is now ready for primetime within the Spring Framework. +Before you build, you'll first need to make sure the axis2-spring-1.1.1.jar and +spring.jar files are in the project's Axis2_HOME/lib directory.

+ +

Note: The service will not deploy if you add the above jars files to the service archive due to cloass loding issues.

+

Now build the source and create an AAR file by typing: +ant

+ +

It'll be created at target/WeatherSpringService.aar. Copy it over +to <tomcat-home>/webapps/axis2/WEB-INF/services, and Axis2 +should deploy it quickly.

+ +

Next test the Web service to see if Spring really will initialize the +weather data for you.

+ + +

Testing Using an RPCServiceClient

+ +

It's as simple as it was for the other Web service, except this time type: +ant rpc.client

+ +

Feel free to browse the code for this client in +src/client/WeatherSpringRPCClient.java. Essentially, this client does the +exact same thing as the client testing the WeatherService, except this one +skips the "Setting the weather" task since the weather data should already +have been set by the Spring framework at startup.

+ +

Thus, you should get the following as output from the client:

+
run.client:
+    [javac] Compiling 1 source file to C:\axis2-1.1.1\samples\pojoguidespring\build\cl
+asses
+     [java] Temperature               : 89.9
+     [java] Forecast                  : Sunny
+     [java] Rain                      : false
+     [java] How much rain (in inches) : 0.2
+ +

Which is exactly the values you set them to be in the +applicationContext.xml file!

+ + +

Summary

+ +

Apache Axis2 is an excellent way to expose your POJOs as Web services, and +Spring adds greater flexibility to your POJOs by adding beans support and +initialization abilities, along with all the other goodies provided by the +Spring framework.

+ + +

For Further Study

+ +

Apache Axis2-http://ws.apache.org/axis2/

+ +

Axis2 Architecture-http://ws.apache.org/axis2/1_0/Axis2ArchitectureGuide.html

+ +

Introduction to Apache Axis2-http://www.redhat.com/magazine/021jul06/features/apache_axis2/

+ +

Working With Apache Axis2-http://www.wso2.net/articles/axis2/java/2006/09/13/working-with-axis2

+ +

Apache Tomcat-http://tomcat.apache.org

+ +

Spring Framework-http://www.springframework.org/

+ + --------------------------------------------------------------------- To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org For additional commands, e-mail: axis-cvs-help@ws.apache.org