Java Tutorial - Java Scipt : Building a Basic Web Service

Java Tutorial - Java Scipt :

Building a Basic Web Service

In this section, we’ll show you how to build a simple price-quoting Web service called SimpleShop. There are several ways to construct a Java Web service with Apache Axis. SimpleShop will use the simplest method: writing the service in the form of a Java source file. This basic Web service has a single exposed method, getPrice. To begin, we’ll just write the Web service as if it were a normal Java class. Here’s the source code for SimpleShop.java:


import java.util.*;
public class SimpleShop
{
protected Map moPrices = null;
public SimpleShop()
{
setupMockPrices();
}

protected void setupMockPrices()
{
moPrices = new HashMap();
moPrices.put( “t-shirt”, new Float( 19.99 ) );
moPrices.put( “coffee cup”, new Float( 10.00 ) );
moPrices.put( “poster”, new Float( 14.95 ) );
}

public float getPrice( String sProductName ) throws Exception
{
// --- Check that the product exists, otherwise throw an
exception. ---
if( !moPrices.containsKey( sProductName ) )
{
throw new Exception( “ProductNotFound” );
}
// --- Return the float price of the product. ---
Float f = (Float) moPrices.get( sProductName );
return f.floatValue();
}
}

Deployment is as simple as renaming the source file with the .jws extension and making available in the Axis Web application’s main directory. Note that we don’t even need to compile it—that’s handled automatically by Apache Axis.

If you renamed the Axis directory, be sure to either change the name
back or adjust the destination directory to the new name. The instructions are
going to assume that it’s still bound under axis.

On Windows, the command is:

copy SimpleShop.java %TOMCAT_HOME%\webapps\axis\SimpleShop.jws

On Linux, it is:

cp SimpleShop.java $TOMCAT_HOME/webapps/axis/SimpleShop.jws

The .jws method of creating a Web service is very similar to JSP in terms of ease and operation. When the Web service is accessed, Axis will generate the appropriate WSDL description and SOAP endpoint from the .jws file.

The URL for retrieving the WSDL description of a Web service can be retrieved from Axis by calling the Web service with wsdl as a query parameter. For example, to see the WSDL for the SimpleShop Web service, the URL is:

Here’s what the WSDL generated for the SimpleShop should look like:

<wsdl:definitions targetNamespace=”http://localhost:8080/axis/SimpleShop.jws”>

<wsdl:message name=”getPriceResponse”>
<wsdl:part name=”getPriceReturn” type=”xsd:float”/>
</wsdl:message>

<wsdl:message name=”getPriceRequest”>
<wsdl:part name=”sProductName” type=”xsd:string”/>
</wsdl:message>

<wsdl:portType name=”SimpleShop”>
<wsdl:operation name=”getPrice” parameterOrder=”sProductName”>
<wsdl:input message=”impl:getPriceRequest” name=”getPriceRequest”/>
<wsdl:output message=”impl:getPriceResponse” name=”getPriceResponse”/>
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name=”SimpleShopSoapBinding” type=”impl:SimpleShop”>
<wsdlsoap:binding style=”rpc”
transport=”http://schemas.xmlsoap.org/soap/http”/>
<wsdl:operation name=”getPrice”>
<wsdlsoap:operation soapAction=””/>
<wsdl:input name=”getPriceRequest”>
<wsdlsoap:body encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”
namespace=”http://localhost:8080/axis/SimpleShop.jws” use=”encoded”/>
</wsdl:input>
<wsdl:output name=”getPriceResponse”>
<wsdlsoap:body encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”
namespace=”http://localhost:8080/axis/SimpleShop.jws” use=”encoded”/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name=”SimpleShopService”>
<wsdl:port binding=”impl:SimpleShopSoapBinding” name=”SimpleShop”>
<wsdlsoap:address location=”http://localhost:8080/axis/SimpleShop.jws”/>
</wsdl:port>
</wsdl:service>

</wsdl:definitions>

Note that we only had to write one Java source file. The WSDL describing our service is generated from that, as are the SOAP and Java Web service endpoints. See? Writing Java Web services with Apache Axis is a snap!

Next, we’ll write a simple client application to access the SimpleShop Web service. There are two ways of writing the client, and we will cover both. The first client, SimpleShopClient, is written using the Axis interface to SOAP. It is a simple Swing application that lets you enter the URL of the Web service and the item whose price should be retrieved. By default, it gets the price of a T-shirt from the SimpleShop Web service we wrote earlier. Tinkering with SimpleShop and the SimpleShopClient is an easy way to get a good picture of the entire process behind a SOAP-based Web service.

Setting up the Web service call and parameters is handled within our code. While not raw XML/SOAP processing, the abstraction level we’re dealing with in this client code is pretty close to that. We will show you a better method using generated Java stubs in SimpleShopClient2 in the next section.
For now, let’s take a look at the hand-coded method of processing a Web services call.

Here’s the source code for SimpleShopClient.java:

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;
import javax.naming.*;
import javax.rmi.*;
import javax.swing.*;
import javax.xml.namespace.*;
import javax.xml.rpc.*;
import org.apache.axis.*;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.*;

public class SimpleShopClient extends JFrame implements ActionListener
{
private Context moContext = null;
private JButton moGetPriceButton = null;
private JTextField moServiceUrlField = null;
private JTextField moItemNameField = null;
private JTextArea moMessageArea = null;

public SimpleShopClient()
{
super( “Simple Shop Client” );
createGui();
}

protected void createGui()
{
setBounds( 50, 50, 500, 500 );
moGetPriceButton = new JButton( “Get Price!” );
moGetPriceButton.addActionListener( this );
moServiceUrlField = new JTextField();
moServiceUrlField.setText(
“http://localhost:8080/axis/SimpleShop.jws” );
moItemNameField = new JTextField();
moItemNameField.setText( “t-shirt” );

moMessageArea = new JTextArea();

JPanel oLabelPanel = new JPanel( new GridLayout( 2, 1 ) );
oLabelPanel.add( new JLabel( “Service URL:” ) );
oLabelPanel.add( new JLabel( “Item:” ) );

JPanel oFieldPanel = new JPanel( new GridLayout( 2, 1 ) );
oFieldPanel.add( moServiceUrlField );
oFieldPanel.add( moItemNameField );

JPanel oTopPanel = new JPanel( new BorderLayout() );
oTopPanel.add( oLabelPanel, BorderLayout.WEST );
oTopPanel.add( oFieldPanel );
oTopPanel.add( moGetPriceButton, BorderLayout.SOUTH );

JPanel oPanel = new JPanel( new BorderLayout() );
oPanel.add( oTopPanel, BorderLayout.NORTH );
oPanel.add( new JScrollPane( moMessageArea ) );

getContentPane().add( oPanel );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}

public void actionPerformed( ActionEvent oActionEvent )
{
if( oActionEvent.getSource() == moGetPriceButton )
{
getPrice();
}
}

protected void getPrice()
{
try
{
Service oService = new Service();
Call oCall = (Call) oService.createCall();
oCall.setTargetEndpointAddress( new URL(
moServiceUrlField.getText() ) );
oCall.setOperationName( “getPrice” );
oCall.addParameter( “product_name”,
XMLType.XSD_STRING,
ParameterMode.IN );
oCall.setReturnType( XMLType.XSD_FLOAT );

Object[] oInputParams = new Object[]
{ moItemNameField.getText() };
Object oReturn = oCall.invoke( oInputParams );
oReturn = (Float) oReturn;

moMessageArea.append( “The price for a “
+ moItemNameField.getText()
+ “ is “ + oReturn + “.\n” );
}
catch( Exception e )
{
JOptionPane.showMessageDialog( null,
e.toString(), “Whoops!”,
JOptionPane.ERROR_MESSAGE );
}
}

public static void main( String args[] )
{
SimpleShopClient oClient = new SimpleShopClient();
oClient.show();
}
}

Notice that in the example we coded the data type specifications for marshaling. Because the Web service’s WSDL description contains the necessary information, we can actually automate the process. Apache Axis provides just
the tool for the task, WSDL2Java. In the next section, we’ll show you how to build SimpleShopClient2 using this tool.