Example of creating a web service that retrieves information from an item

This example shows how to create a web service that retrieves information from an item, and returns a custom object to the web service. This example also demonstrates the use of Java2WSDL and WSDL2Java in creating WSDD.

About this task

This example creates a web service that enables you to query a catalog with a primary key and get back a Java™ object instance that represents a catalog-specific item. The catalog is for books, so items have a primary key attribute of ISBN and other attributes such as title and author. The web service allows users to query the catalog and get an instance of a custom book class. Users can then query this instance in application code.

Procedure

  1. Write the Java code. Here is a sample:
    Main Class:
    public class BookCatalogService
    {
        /**
         * Queries the specified catalog for the book with the specified ISBN
         * number.
         */
        public Book getBookFromCatalog(String catalogName, String isbnNumber) throws Exception
        {
            Context context = null;
            try
            {
                context = PIMWebServicesContextFactory.getContext();
                CatalogManager catalogManager = context.getCatalogManager();
                Catalog catalog = catalogManager.getCatalog(catalogName);
    
                if (catalog == null)
                {
                    throw new Exception("No Catalog found.");
                }
                else
                {
                    Item item = catalog.getItemByPrimaryKey(isbnNumber);
                    if (item == null)
                    {
                        throw new Exception("No matching Item found.");
                    }
                    else
                    {
                        System.out.println("Item was " + item);
                        /*
                         * Now we have an item, we can extract the application
                         * specific details and populate our application object
                         * instance
                         */
                        Book book = new Book();
                        book.setISBN(Integer.parseInt(item.getPrimaryKey()));
    
                        // The spec name is required to qualify fully the attribute
                        // name
                        String spec = "BookSpec";
    
                        book.setAuthor(item.getAttributeValue(spec + "/" + "Author").toString());
                        book.setTitle(item.getAttributeValue(spec + "/" + "Title").toString());
                        book.setDescription(item.getAttributeValue(spec + "/" + "Description").toString());
                        book.setPrice(Float.parseFloat(item.getAttributeValue(spec + "/" + "Price").toString()));
                        book.setStockLevel(Integer.parseInt(item.getAttributeValue(spec + "/" + "StockLevel").toString()));
    
                        return book;
                    }
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
                throw new Exception(e.getMessage());
            }
        }
    
    }
    
    Book Object Class:
    public class Book
    {
        private int ISBN;
        private String title;
        private String author;
        private String description;
        private float price;
        private int stockLevel;
    
        public String getAuthor()
        {
            return author;
        }
    
        public void setAuthor(String author)
        {
            this.author = author;
        }
    
        public String getDescription()
        {
            return description;
        }
    
        public void setDescription(String description)
        {
            this.description = description;
        }
    
        public int getISBN()
        {
            return ISBN;
        }
    
        public void setISBN(int isbn)
        {
            ISBN = isbn;
        }
    
        public float getPrice()
        {
            return price;
        }
    
        public void setPrice(float price)
        {
            this.price = price;
        }
    
        public int getStockLevel()
        {
            return stockLevel;
        }
    
        public void setStockLevel(int stockLevel)
        {
            this.stockLevel = stockLevel;
        }
    
        public String getTitle()
        {
            return title;
        }
    
        public void setTitle(String title)
        {
            this.title = title;
        }
    }
    
    The following code is the custom Java object that represents a book in the catalog and is passed back by the web service.
    /**
     * Simple application wrapper class which represents an Item from a
     * catalog for books.
     */
    public class Book {
        private int ISBN;           
        private String title;             
        private String author;             
        private String description;             
        private float price;             
        private int stockLevel; 
        
        public String getAuthor() {
            return author;
        }
        public void setAuthor(String author) {
            this.author = author;
        }
        public String getDescription() {
            return description;
        }
        public void setDescription(String description) {
            this.description = description;
        }
        public int getISBN() {
            return ISBN;
        }
        public void setISBN(int isbn) {
            ISBN = isbn;
        }
        public float getPrice() {
            return price;
        }
        public void setPrice(float price) {
            this.price = price;
        }
        public int getStockLevel() {
            return stockLevel;
        }
        public void setStockLevel(int stockLevel) {
            this.stockLevel = stockLevel;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
    }
  2. Generate the WSDD for the web service.

    This step shows how to use two Axis utilities: Java2WSDL and WSDL2Java to create WSDD for a web service. Java2WSDL creates WSDL that represents Axis's view of the web service that is implemented by the specified class. WSDL2Java creates Java classes from WSDL to implement a web service that uses Axis. More importantly, WSDL2Java is able to create a WSDD document that can be used to deploy that service to Axis. The generated WSDD contains the definitions for serializers that Axis expects to use for the web service.

    1. Create a temporary directory.
      For example ws_tmp to use while you generate the WSDL and WSDD. Type mkdir ws_tmp.
    2. Go to the temporary directory. Type cd ws_tmp.
    3. Add the Axis .jar files to your CLASSPATH, so you can run the Axis tools.
      Note: This code is for Windows. It will differ on other platforms. Also the directory for Axis might differ on your system.
      set CLASSPATH=%CLASSPATH%;C:\Axis\lib\axis.jar;
      C:\Axis\lib\jaxrpc.jar;C:\Axis\lib\commons-logging-1.0.4.jar;
         C:\Axis\lib\commons-discovery-0.2.jar;C:\Axis\lib\wsdl4j-1.5.1.jar;
      C:\Axis\lib\saaj.jar;
      
      Note: There is no line break in this command. Replace C:\Axis\lib with the location of your Axis lib directory.
    4. Run Java2WSDL to generate the WSDL that describes your web service. Type:
      java org.apache.axis.wsdl.Java2WSDL 
      -o BookCatalogService.wsdl 
      -l "http://myWpcHost:9080/services/BookCatalogService " 
         -n "http://javawbs.acme.com" 
      com.acme.javawbs.BookCatalogService -y WRAPPED
       -u LITERAL
      
      Do not include the line break. Where http://myWpcHost:9080/services/BookCatalogService is the URL for the service that you plan to deploy, in the format:
      http://wpcHostname:wpcPort/services/WebServiceName
      wpcHostname is the name that you give when you deploy the web service in the console. -n http is the namespace that is used to distinguish your WSDL from other namespaces (inverting the package name is convention, but any String that is unique to your installation should work). com.acme.javawbs.BookCatalogService is the fully qualified name of the Java class that implements the service. BookCatalogService.wsdl is the output file name for the WSDL. -y WRAPPED -u LITERAL ensures that the generated WSDL is wrapped-document/literal based, which is the correct type for IBM® Product Master document/literal deployments. For rpc/encoding, use -y RPC -u ENCODED.

      You get a WSDL document.

    5. Run WSDL2Java to generate the WSDD file. Type:
      java org.apache.axis.wsdl.WSDL2Java \-o .
       \-d Session \-s \-S true wp.wsdl
      
      BookCatalogService.wsdl is the output file name from the previous step. -S true can be changed to -S false to generate individual entries for each operation, which can be needed for more complex services, such as those returning arrays of custom types.

      After WSDL2Java runs, a directory tree that contains generated Java appears in your temporary directory. With Java, there is an example WSDD document for the service that is called deploy.wsdd, which can be used as a template for your own WSDD file.

    6. Edit the WSDD file for use with Product Master. Open the generated WSDD document: more com/acme/javawbs/deploy.wsdd Where com/acme/javawbs is the package name of the web service implementation class. Make the following changes:
      • Change provider="java:RPC" to provider="java:WPCDocument". For document literal or for RPC/Encoded based services, use: provider="java:WPCRPC". This change is required, to ensure Product Master security. The web Services Console does not save a service that is based on a default Axis provider because these services do not validate Product Master user names for authenticated services.
      • Change <parameter name="className" value="..."> to <parameter name="className" value="com.acme.javawbs.BookCatalogService"> where the value= parameter is the fully qualified class name of the implementation class. The output XML is a valid WSDD document that can be entered into the WSDD field when you deploy the web service to Product Master.
    7. Clean up your directories. The entire ws_tmp directory can be cleaned up and deleted after the deploy.wsdd and BookCatalogService.wsdl files are copied elsewhere.
  3. Deploy the user .jar file.
  4. Register the web service in Product Master.
    1. Access your Product Master instance and log in.
      For example: http://yourWPCserver:yourWPCport/utils/enterLogin.jsp.
    2. Click Collaboration Manager > Web Services > Web Service Console > New.
    3. Provide the following values:
      • Web Service Name: Provide a name. For example, CatalogService.
      • WSDL: Copy and paste the entire contents of BookCatalogService.wsdl into the WSDL field.
      • Web Service Implementation: Select Java.
      • Java Implementation Class: Type the Java class of your web service. For the above example, you type com.acme.javawbs.CatalogService.
      • WSDD: Copy and paste the entire contents of your edited copy of deploy.wsdd into the WSDD field.
      • Deployed: Select this check box. Clearing this selection stores web services in an inactive (unusable) state.
      • Authenticated: Do not select this check box.

        Authenticated means that the web service expects a user name and password to be supplied. This is done through an Axis menu dialog if you call the web service through the web browser, or if you are using a custom Java client then the user name and password must be included in the SOAP header. The correct format for an Axis user name is "User@Company" for example "Joe@Acme".

        Unauthenticated means that the web service contacts Product Master using the user name and company that is specified in the soap_company and soap_user fields in $TOP/etc/default/common.properties. In this scenario, the password will not be checked. Only the administrator should have access to change files on the Product Master server, so this is not constituted a security risk. To protect against unauthorized access, administrators should ensure that the SOAP company and user that are specified for Product Master in common.properties should not be an Admin user.

        The two fields can be kept blank to disable unauthenticated access completely.

        If the service cannot be authenticated, a SOAP fault is returned in the message body.

    4. Click Save. If you get an error similar to: Unable to verify Java implementation class, and you have no typographical errors in your fully qualified Java class name, then you did not successfully deploy your Java class through the user .jar mechanism. Return to Step 2 and check whether your user .jar appears in your class path.
      For example, ps -ef | grep java and check the Java process for Product Master. Your web service is now deployed.
  5. Access the web service through the service URL, or generate your own Java application client.

    For more information, see Example of creating a web service that uses a business object and complex logic.

    You can now write a Java client application that starts your web service through the generated Java proxy, which enables you to write business logic easily. Here is an example of some client code:
    /**
     * Test the BookCatalogService via a generated proxy.
     */
    public class BookCatalogApplication {
    
        public static void main(String[] args)
     {
            BookCatalogServiceProxy bookCatalogServiceProxy = new BookCatalogServiceProxy();
            try {
                Book book = bookCatalogServiceProxy.getBookFromCatalog("BookCatalog", "140035206");
                System.out.println("Got the Book instance as : " + book);
                if(book != null){
                    System.out.println("ISBN : " + book.getISBN());
                    System.out.println("Author : " + book.getAuthor());
                    System.out.println("Description : " + book.getDescription());
                    System.out.println("Price : " + book.getPrice());
                    System.out.println("StockLevel : " + book.getStockLevel());
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }