Step 3. Create JAX-WS WebLogic Web Services for Spring beans 

Time to complete this step: 20 minutes

You can use the Oracle Enterprise Pack for Eclipse (OEPE) to automatically generate WebLogic Web Service to expose Spring service delegates/beans.

During previous tutorial part for Spring, you have developed Spring service delegates/beans for various DAOs of the Trouble Ticket System. In this step, you will use the OEPE for generating JAX-WS WebLogic Web Services for the TroubleTicketSystemServer Spring delegates/beans. The Web Services will use the JAXB types generated in the previous step for messaging.

You will perform the following tasks in this step:


Import the utility/helper classes 

Copy the following Java classes from the extracted resources folder to the com.oracle.ticketsystem.util package.

  1. Utils.java   
    Overwrite the existing Utils class. The Utils class has additional methods for providing a reference of a TicketSystemException  based on the given error message and a Throwable instance. 
  2. TicketSystemException.java
    An exception class to represent error situation while running the web service operation. The TicketSystemException class is annotated with @WebFault annotation that maps the WSDL faults to Java exceptions.
  3. Adapter.java:
    An adapter class with static helper methods for converting the given JPA beans to the corresponding JAXB type.

Open each copied class and review the code.

 

Create the JAX-WS WebLogic Web Services for Spring beans


  1. In the Project Explorer view, right-click the  TroubleTicketSystemServer project and select New > WebLogic Web Service for Spring beans. This will open the Select Spring Service Bean wizard page. 

  2. On the wizard dialog, provide the following information:
    • Select the Spring bean configuration file i.e. /TroubleTicketSystemServer/WebContent/Web-INF/applicationContext.xml.
    • Select the LoginDelegate Spring bean that we want to expose as WebLogic Web Service. (Note: the wizard does not support Spring ORM service beans implemented in Spring 1.x style based on JPA Templates and TransactionProxyFactoryBeans.)
    • The selection of the LoginDelegate Spring bean highlights the Spring service delegate interface and its operations defined. Make sure that com.oracle.ticketsystem.delegates.ILoginDelegate is selected as the type and the login item is selected as the method. (Note: a service bean can implement multiple interfaces but service methods from only one interface can be generated in this wizard.)

  3. Click Next
  4. This will open the Web Service Class Name wizard page. Specify the com.oracle.ticketsystem.webservices as the package and LoginWebService as class name for the web service.  

  5. Click Finish. The JAX-WS WebLogic Web Service class ( LoginWebService) is generated in the com.oracle.ticketsystem.webservices package. The web service class contains methods exposed from the Spring bean.

  6. Similarly, generate JAX-WS WebLogic Web Services for the Spring delegates/beans ProductDelegate and TicketDelegate with the name ProductWebService and TicketWebService in the com.oracle.ticketsystem.webservices package. Make sure that all the methods of the Spring delegates/beans are selected.

  7. Open the generated JAX-WS WebLogic Web Service class  LoginWebService and review the code.

    @WebService
    public class LoginWebService extends SpringBeanAutowiringSupport
    {
      public static String BEAN_ID = "LoginDelegate";
     
      @Autowired
      @Qualifier("LoginDelegate")
      private ILoginDelegate springServ;

      @Resource
      private WebServiceContext wsContext; 
     
      private void getSpringService() throws Exception {
        if(springServ ==null ) {
           //@Autowired does not work in JAX-WS web services on WebLogic server 10.3
           //fall back to get the spring bean from WebApplicationContext
           ServletContext servletContext= (ServletContext)wsContext.getMessageContext().get(MessageContext.SERVLET_CONTEXT);   
           WebApplicationContext webContext = WebApplicationContextUtils.getWebApplicationContext( servletContext );         
           springServ = (ILoginDelegate)webContext.getBean(BEAN_ID);
           if( springServ == null )
              throw new Exception("Spring service not available: " + BEAN_ID);
        } 
      }

      @WebMethod
      public Technician login(String id,String pwd) throws Exception {
        getSpringService();
        return springServ.login( id,pwd );
      }
    }



  8. The generated JAX-WS WebLogic Web Service classes extends the  SpringBeanAutowiringSupport class, which is a convenient base class for self-autowiring classes in Spring-based web applications. It resolves @Autowired annotations in the endpoint class against beans in the current Spring root web application context.
  9. The  LoginWebService class is annotated with the @WebService annotation. The @WebService annotation marks a Java class as implementing a Web service or marks a service endpoint interface (SEI) as implementing a Web service interface.
  10. The @Resource annotation marks the  WebServiceContext as a resource needed by the application and is injected by the server container.
  11. The  login() method of the LoginWebService class is annotated with the @WebMethod annotation to denotes it as a web service operation. It first calls the  getSpringService() method to intialize the  LoginDelegate spring delegate/bean from  WebServiceContext.  
  12. Open the other generated JAX-WS WebLogic Web Service classes and review the code.
     

Edit the generated JAX-WS WebServices to use the JAXB types for messaging 

The web service operations of the generated JAX-WS WebLogic Web Service classes uses the JPA beans for messaging; i.e., it accepts JPA beans as input and returns the same as output. That means the web service client has to depend on JPA beans and thus the server side complexities is now released to the outside world. This can be avoided and we can use the JAXB types generated in the previous step for messaging. For that we need to modify the web service operation/method signature.

Since, the web service operation parameters are not annotated with @WebParam annotations, the message part names of the generated WSDL will have name like args0, args1, .... Thats not very readable, hence you will also annotate each parameter of the web service operation with the @WebParam annotation. The name parameter of @WebParam annotation describes the name of the wsdl:part attribute representing the parameter. 

Edit the web service operation signature of LoginWebService

  1. Open the  LoginWebService class.
  2. Specify @WebParam for each input argument of the login() operation as shown below: 
    Note: when the Java Editor is active, press Ctrl+Shift+O to organize imports.

     @WebMethod
     public Technician login(
       @WebParam(name="id")
       String id,
       @WebParam(name="pwd")
       String pwd)
    throws Exception {
      
        getSpringService();
        return springServ.login( id,pwd );
     }



  3. To report any runtime failure, while executing the web service operation, use the provided TicketSystemException  class. The TicketSystemException  class is annotated with the @WebFault annotation that maps the WSDL faults to Java exceptions. Change the  login()  operation signature and implementation to throw a TicketSystemException  instead of Exception  class. 

     @WebMethod
     public Technician login(
       @WebParam(name="id")
       String id,
       @WebParam(name="pwd")
       String pwd) throws TicketSystemException {
      
       try {
          getSpringService();
        
          return springServ.login( id,pwd );
       
       } catch(Exception ex) {
          throw Utils.getTicketSystemException("Login failed", ex);
       }

     }



    Note: when the Java Editor is active, press Ctrl+Shift+O to organize imports. Make sure to choose the com.oracle.ticketsystem.util.Utils.
  4. The  login() operation returns the  Technician JPA entity bean. Edit its signature to return the TechnicianType JAXB type instead of  Technician JPA entity bean. Use the provided  Adapter helper class for converting the  Technician  JPA entity bean to the TechnicianType  JAXB type.

     @WebMethod
     public TechnicianType login(
       @WebParam(name="id")
       String id,
       @WebParam(name="pwd")
       String pwd) throws TicketSystemException {
      
       try {
         getSpringService();
       
         Technician technician = springServ.login( id, pwd );
         return Adapter.adapt(technician);
       
       } catch(Exception ex) {
         throw Utils.getTicketSystemException("Login failed", ex);
       }
     } 



    Note: when the Java Editor is active, press Ctrl+Shift+O to organize imports. Make sure to choose the com.oracle.ticketsystem.util.Adapter.

  5. Save the  LoginWebService class. 

Edit the web service operation signature of ProductWebService

  1. Open the  ProductWebService class. You can either copy the ProductWebService class from the  resources folder (to save time) or follow the instructions here for editing it. 
  2. Specify @WebParam for each input argument of the  getProduct() operation as shown below:  Note: when the Java Editor is active, press Ctrl+Shift+O to organize imports: in cases where multiple options are presented, ensure to import com.oracle.ticketsystem.util.Utils, com.oracle.ticketsystem.util.TicketSystemException, com.oracle.ticketsystem.util.Adapter.

     @WebMethod
     public Product getProduct(
        @WebParam(name="id")
       long id) throws Exception {
      
        getSpringService();
        return springServ.getProduct( id );
     }



  3. Change the signature and implementation of  getAllProducts() and  getProduct() operations to throw TicketSystemException instead of Exception class. 

     @WebMethod
     public List<Product> getAllProducts() throws TicketSystemException {
      
       try {
       
         getSpringService();
         return springServ.getAllProducts(  );
      
       } catch (Exception e) {
         throw Utils.getTicketSystemException("getAllProdcts operation failed", e);
       }
     }

     @WebMethod
     public Product getProduct(
       @WebParam(name="id")
       long id) throws TicketSystemException {
      
       try {
       
         getSpringService();
         return springServ.getProduct( id );
      
       } catch (Exception e) {
         throw Utils.getTicketSystemException("getProduct operation failed", e);
       }
     } 



  4. The  getAllProducts() operation returns a  java.util.List of  Product JPA entity beans. Edit its signature to return a ProductResultType JAXB type instead of the list of  Product JPA entity beans. Use the provided  Adapter helper class for converting the  java.util.List of  Product JPA entity bean to the ProductResultType JAXB type.

     @WebMethod
     public ProductResultType getAllProducts() throws TicketSystemException {
      
      try {
       
        getSpringService();
       
        List<Product> products = springServ.getAllProducts();
        ProductResultType result = Adapter.adapt(products);
       
        return result;
       
      } catch (Exception e) {
        throw Utils.getTicketSystemException("getAllProdcts operation failed", e);
      }
      
     } 



  5. The  getProduct()  operation returns the  Product JPA entity beans. Edit its signature to return a ProductType JAXB type instead of the  Product JPA entity bean. Use the provided  Adapter helper class for converting the  Product JPA entity bean to the ProductType JAXB type.

     @WebMethod
     public ProductType getProduct(
       @WebParam(name="id")
       long id) throws TicketSystemException {
      
      try {
       
        getSpringService();
       
        Product product = springServ.getProduct( id );
        ProductType productType = Adapter.adapt(product);
        return productType;
      
      } catch (Exception e) {
       throw Utils.getTicketSystemException("getProduct operation failed", e);
      }
      
     } 



  6. Save the  ProductWebService class. 

Edit the web service operation signature of TicketWebService

  1. Open the  TicketWebService class. 
  2. For each web service operation of  TicketWebService perform following steps:
    Note: To save time either you can copy the provided  TicketWebService class from the  resources folder.
    • Specify @WebParam for each input argument of the web service operation.
    • Change the signature and implementation of operations to throw a TicketSystemException instead of Exception class.
    • Change the signature and implementation of the web service operations to return the JAXB type instead of the JPA entity bean.
      • For the add() , update() , and get() opeations return the  TicketTypeJAXB type instead of  Ticket JPA entity bean
      • For the getTicketsOwnedByTechnician() , and getOpenTickets() opeations return the  TicketResultType JAXB type instead of  java.util.List of the Ticket JPA entity bean
      • Use the provided  Adapter helper class for converting the JPA entity bean to the corresponding JAXB type.

Click the arrow below to navigate through the tutorial: