Java-SE-based Web Services
admin originally posted this on Wayne Adams' Blog.
This isn't exactly late-breaking news, as Java SE6 has been out for a while, but the Standard Edition now includes support for non-trivial web-service development and deployment, no Java-EE application server necessary. The purpose of this very quick introduction is to produce a working web service and a web service client, in as few lines of Java as possible, without relying on heavy infrastructure (namely, an IDE and/or an application server). The output of this post will re-appear in subsequent posts, for example when I need a quick client to kick off a BPEL (Business Process Execution Language) process, or simply to exercise a web service to verify deployment.Pre-requisites:
- Java SE 6 installed: http://java.sun.com/javase/downloads/index.jsp. Be sure to get the JDK, not the JRE, as there are utilities you will need from the JDK.
- Maven 2 installed: http://maven.apache.org/download.html
- The following environment variables:
- JAVA_HOME: top-level Java SE 6 directory
- M2_HOME: top-level Maven 2 directory
- M2: $M2_HOME/bin or %M2_HOME%\bin
- MAVEN_OPTS: -Xms256m -Xms512m (optional)
- PATH: $JAVA_HOME/bin:$M2:$PATH or %JAVA_HOME%\bin;%M2%;%PATH%
As you've guessed, I'm using Maven to build this service. Maven will generate the project directory for you, so there's no need to create it first. Just open a command prompt or shell in a development directory and enter the following:
mvn archetype:generate -DgroupId=com.example.webservice -DartifactId=JavaSEWebService
substituting your desired package name for groupId. The artifactId will be the name of the project directory Maven will create in your current working directory. You will be asked for an archetype, where the default is 15, or maven-archetype-quickstart. Select defaults by hitting "Enter" until Maven generates the project.
Next, create a simple web service. Note: I prefer to start with a WSDL definition first, then generate the server and client-side artifacts from it, but for this quick example we'll go in the opposite direction, taking a small piece of business logic and exposing it as a service.
cd to the the groupId-defined package under the source branch (./{artifactId}/src/main/java/...) of the newly-created project. There will be a class called App.java. We will ignore this class and create our own.
- Create a directory called service and cd into it.
- Create a Java class called Tutorial.java.
- Add a couple of methods; one called getHelloWorld that takes no arguments and returns the String "Hello, World!" and a second one called getPersonalizedHelloWorld that takes a String and returns a personalized greeting.
- Add a main method, and in it, instantiate a Tutorial and publish it, using the javax.xml.ws.Endpoint class, on your machine. Annotate the class as a WebService and the methods as WebMethods.
An example class is shown here:
package com.example.webservice.service;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
@WebService
public class Tutorial
{
public static void main( String[] args )
{
Tutorial wsInstance = new Tutorial();
Endpoint.publish("http://localhost:8282/tutorial", wsInstance);
}
@WebMethod
public String getHelloWorld()
{
return "Hello, World!";
}
@WebMethod
public String getPersonalizedHelloWorld(String yourName)
{
return "Hello, " + yourName + "!";
}
}
Next we'll modify the Maven "pom" (Project Object Model) file, first to use Java SE 6 (Maven defaults to 1.3) and secondly to specify the wsgen Maven plugin. wsgen creates all the artifacts necessary to build and deploy the web service. cd into the project directory and open the pom.xml file. Add the following to your pom:
Save and close the file. From the project directory, enter mvn install. You should get a clean build. Note that the name of the produced .jar file is obtained from the finalName element in the pom.xml file. Start the web service from the project-level directory with:
<build>
<finalName>tutorialWebService</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>wsgen</goal>
</goals>
<configuration>
<sei>com.example.webservice.service.Tutorial
</sei>
<genWsdl>true</genWsdl>
<keep>true</keep>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
java -cp target/tutorialWebService.jar com.example.webservice.service.Tutorial
and verify that the service is available by retrieving the WSDL description in a browser. Append ?wsdl to the endpoint URL you defined in your Java class, in this case
http://localhost:8282/tutorial?wsdl
Note that depending on the browser you are using, you may need to view the page source to see the WSDL description.
We'll create a new Maven project for the client. Open another command prompt or shell in your development directory (again, no need to create the project directory, as Maven will do this for you), and enter the following:
mvn archetype:generate -DgroupId=com.example.webservice -DartifactId=JavaSEWebServiceClient
substituting your desired package name for groupId. The artifactId will be the name of the project directory Maven will create in your current working directory. As for the web service example, you will be asked for an archetype, where the default is 15, or maven-archetype-quickstart. Select defaults by hitting "Enter" until Maven generates the project.
cd into the project directory, given by the value you supplied for artifactId (for this example, JavaSEWebServiceClient). Open the pom.xml (Maven Project Object Model) file. Add the following to the POM; wsimport is used to generate client stubs for your web service:
<build>
<finalName>tutorialWebServiceClient</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlUrls>
<wsdlUrl>http://localhost:8282/tutorial?wsdl</wsdlUrl>
</wsdlUrls>
<packageName>com.example.webservice.service
</packageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Save and close the file. Note that you are directing Maven to obtain the WSDL description via the URL we used earlier to verify that the web service was correctly deployed.
Create a simple web service client:
- cd to the groupId-defined package under the source branch (./{artifactId}/src/main/java/...) and create a client directory; cd into this directory.
- Create a Java class called TutorialWebServiceClient.java.
- Create a main method which gets a reference to the tutorial web service and exercises its two operations. For example:
package com.example.webservice.client;
import com.example.webservice.service.Tutorial;
import com.example.webservice.service.TutorialService;
public class TutorialWebServiceClient
{
public static void main(String[] args)
{
TutorialService service = new TutorialService();
Tutorial port = service.getTutorialPort();
System.out.println("Calling getHelloWorld(); returns '" + port.getHelloWorld() + "'");
System.out.println("Calling getPersonalizedHelloWorld(\"Bob\"); returns '" +
port.getPersonalizedHelloWorld("Bob") + "'");
}
}
Note that the wsimport utility will create an interface named TutorialService.java and a class named Tutorial.java. It will do this before the client is compiled, but if you want to see the stub classes before you build the client, just execute mvn install before creating the client.
The web service interface name is obtained by prepending the package name from the POM to the name of the web service portType from the WSDL description, and the name of the service itself is the serviceName from the WSDL description, if you want to reference the classes before they are generated by wsimport.
Also note that the endpoint URL of the web service was embedded into the generated client-side classes by the setup in the Maven POM file, as I mention above.
From the project directory, enter
mvn install
This will generate the client-side stubs you need in your client, followed by the client itself. You can safely ignore the "[INFO] Nothing to do, no WSDL found!" log message; it is misleading and if you get a "BUILD SUCCESSFUL" message, then all is well.
Test the client and the web service with:
java -cp target/tutorialWebServiceClient.jar com.example.webservice.client.TutorialWebServiceClient
You should see output like the following:
Calling getHelloWorld(); returns 'Hello, World!'
Calling getPersonalizedHelloWorld("Bob"); returns 'Hello, Bob!'
You now have a working web-service/client pair, which will come in handy in future entries as we explore Flex web-service clients, BPEL and JBI.