6.2.  Create a client in a managed component in a EE container.

6.2.1.  Use wsimport to generate artifacts.

blah-blah

6.2.2.  Using @WebserviceRef in the client application.

The @WebServiceRef annotation is used to declare a reference to a web service.

Use the @WebServiceRef annotation to inject a reference to the service you want to invoke. Note that this does not have to be only a servlet or EJB. You might also want to invoke a web service from other container-managed resources, such as a Filter, a SessionContextListener, a ServletContextListener, or a TagHandler depending on your use case.

Using @WebServiceRef, you can get a reference to a web service and an injection target for it. Items annotated with @WebServiceRef follow the standard rules for resource injection within Java EE 6. It defines follwoing attributes or properties, as are described below:

  • name

    A name that identifies the reference to the component using the resource, as a JNDI name. If annotating a field, the default is the name of the field. If annotating a method, the default is the name of the Java Bean property the method defines. If annotating a class, there is no default.

  • wsdlLocation

    The URL pointing to the WSDL for the referenced web service. This is necessary if you define your own WSDL in a physical file and include it with your WAR or EAR.

  • type

    The resource class type. If annotating a field, the default value is the type of the field. If annotating a method, the default is the same as the Java Bean property. If annotating a class, there is no default, and a value must be specified.

  • value

    The service class type, which must extend javax.xml.ws.Service. If the reference type is an SEI, this value must be specified.

  • mappedName

    A name, such as a JNDI name, that maps from the value of the "name" property to a resource known to the server. Any mappedName value is specific to the application server platform, and is non-portable. It is not required that application servers support them.

  • lookup

    A portable JNDI lookup name that resolves to the target web service reference.

Here you will write a servlet that invokes the web service by injection using the @WebServiceRef annotation. There are a few steps, which are exactly the same for using the reference from an EJB client:

  1. Create the interface that the web service will implement, and to which clients, such as your servlet, will refer.

  2. Implement the web service.

  3. Add the reference annotation to the servlet; an instance of the generated SEI will automatically be injected.

Catalog.java in the example below is the interface that clients will refer to. It defines a simple operation that returns a book title for a given identifier:

package by.boot.java;

import javax.jws.WebMethod;
import javax.jws.WebService;

/**
 * Public interface for CatalogWS implementation
 */
@WebService
public interface Catalog {

    @WebMethod
    String getTitle(String id);

}
						

Note that you need to include the @WebService annotation on the interface, or the client will complain.

CatalogWS.java, shown in the example below, implements the service interface:

package by.boot.java;

import javax.jws.WebMethod;
import javax.jws.WebService;

/**
 * This annotation will produce a WSDL URL of:
 * http://localhost:8080/catalogWS/CatalogService?wsdl
 * That's because it is in the web context of "catalogWS",
 * which is the WAR name, appended with the value of the
 * serviceName property.
 *
 * Use that value in the properties file to generate client
 * artifacts.
 */
@WebService(serviceName="CatalogService", name="Catalog")
public class CatalogWS implements Catalog {

    @WebMethod
    @Override
    public String getTitle(String id) {
        if ("12345".equals(id)) return "OCE WSD 6 Guide";
        if ("67890".equals(id)) return "OCE WSD 6 Quiz";
        return "Item not in catalog";
    }

}
						

The code in the example below is the servlet that will get the @WebServiceRef annotation and receive the service injection from the container at runtime:

@WebServlet(name="CatalogServlet", urlPatterns={"/CatalogServlet"})
public class CatalogServlet extends HttpServlet {

    @WebServiceRef(type=Catalog.class)
    private CatalogService service;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        // Service instance injected
        Catalog port = service.getCatalogPort();
        String title = port.getTitle("12345");

        try {
            out.println("...");
            out.println("Title= " + title);
            out.println("...");
        } finally {
            out.close();
        }
    }
}
						

The servlet itself contains the reference to the generated SEI proxy instance, and the container does the injection as it would with any other injectable resource.

There are two ways to use the @WebServiceRef annotation:

  • To define a reference whose type is a generated service class. In this case, the type and value element will both refer to the generated service class type. Moreover, if the reference type can be inferred by the field/method declaration the annotation is applied to, the type and value elements MAY have the default value (Object.class, that is). If the type cannot be inferred, then at least the type element MUST be present with a non-default value.

    // Generated Service Class
    @WebServiceClient(name="StockQuoteService",
        targetNamespace="...",
        wsdlLocation="...")
    public class StockQuoteService extends javax.xml.ws.Service {
    
        @WebEndpoint(name="StockQuoteHTTPPort")
        StockQuoteProvider getStockQuoteHTTPPort() { ... };
        ...
    }
    									

    // Generated SEI
    @WebService(name="StockQuoteProvider",
        targetNamespace="...")
    public interface StockQuoteProvider {
        Double getStockQuote(String ticker);
    }
    									

    // WebServiceRef using the generated service interface type
    @WebServiceRef
    public StockQuoteService stockQuoteService;
    									

  • To define a reference whose type is a SEI. In this case, the type element MAY be present with its default value if the type of the reference can be inferred from the annotated field/method declaration, but the value element MUST always be present and refer to a generated service class type (a subtype of javax.xml.ws.Service).

    // WebServiceRef using the SEI type
    // stockQuoteProvider proxy is configured with MTOM feature
    @MTOM
    @WebServiceRef(StockQuoteService.class)
    private StockQuoteProvider stockQuoteProvider;
    									

    or

    // WebServiceRef using the SEI type
    @WebServiceRef(value=StockQuoteService.class)
    private StockQuoteProvider stockQuoteProvider;
    									

The value of the wsdlLocation property will override the URL established in the generated service class (the class annotated with @WebService).

6.2.3.  Package and deploy accordingly.

Packaging a servlet endpoint using a WAR

Figure 6.1. Servlet endpoint packaging

Servlet endpoint packaging.


  1. Service Implementation Bean [required] is contained in the WEB-INF/classes/<package-path>/, where <package-path> is determined by the class's package name. This location is not mandatory, but customary. Alternatively, the SIB could be contained in a JAR under the WEB-INF/lib or even in an extension JAR installed in the web container and referenced by the WAR's MANIFEST Class-Path. As long as the SIB is on the application classpath, the packaging will work. This class file must be annotated with @WebService or @WebServiceProvider. Its methods contain the business logic that implements the web service operations.

  2. Service Endpoint Interface [optional] is contained in the WEB-INF/classes/<package-path>/ where <package-path> is determined by the class's package name. This location is customary, but not mandatory. The SEI class file may be located anywhere on the application classpath (see classpath description in item 1). When used, the SIB's @WebService.endpointInterface attribute's value must equal the complete name of this SEI.

  3. WSDL [optional] is contained in the WEB-INF/wsdl directory. This is not a mandatory location, but is customary. When used, the SIB's @WebService.wsdlLocation attribute's value must equal the relative location of this file (the wsdlLocation can also be an absolute URL). Any files (e.g., XML Schema definitions) referenced by the WSDL must be referenced relative to the WSDL's location. For example, if the WSDL is in the WEB-INF/wsdl directory and it references a schema as myschema.xsd, then myschema.xsd should be in WEB-INF/wsdl. If the schema is referenced as ../myschema.xsd, myschema.xsd should be in WEB-INF.

  4. web.xml [optional] is contained in the WEB-INF/ directory.

  5. webservices.xml [optional] is contained in the WEB-INF/ directory.

  6. jax-ws-catalog.xml [optional] is contained in the WEB-INF/ directory. This descriptor is used in connection with OASIS XML Catalog 1.1 usage.

  7. sun-web.xml [optional] is contained in the WEB-INF/ directory. This is the GlassFish-specific web application descriptor.

  8. Handler Chain Descriptor [optional] is contained under the WEB-INF/classes/ directory where it will be available as a resource on the application classpath. There is no standard name for this file. This is not a mandatory location — it may also be specified as an external URL. Specifically, when used, the SIB's @HandlerChain.file attribute's value must equal either:

    • An absolute java.net.URL in external form (e.g., http://java.boot.by/handlers.xml).

    • A relative path from the source file or class file (e.g., bar/handlers.xml) specifying the location of this file.

  9. Dependent Classes [optional] are bundled in a JAR and contained under the WEB-INF/lib directory where they are available on the application classpath. These are any classes the SIB or SEI depend on. This is not a mandatory location, but one possible approach when the SIB depends on a library of classes that may already be packaged in a JAR. The dependent classes may be located anywhere on the application classpath (see classpath description in item 1).

Packaging an EJB endpoint using an EJB-JAR

Figure 6.2. Stateless or Singleton session bean endpoint packaging

Stateless or Singleton session bean endpoint packaging


  1. Service Implementation Bean [required] is contained in the <package-path>/ directory where <package-path> is determined by the class's package name. This location is not mandatory, but customary. Alternatively, the SIB could be contained in another JAR (e.g., bundled within an EAR with this same EJB-JAR) and referenced by the EJB-JAR's manifest file Class-Path attribute. You could even have the SIB located in an installed library and referenced by the EJB-JAR's manifest file Extension-List attribute. As long as the SIB is on the application classpath, the packaging will work. This class file must be annotated with @Stateless or @Singleton, and @WebService or @WebServiceProvider. Its methods contain the business logic that implements the web service operations.

  2. Service Endpoint Interface [optional] is contained in the <package-path>/ where <package-path> is determined by the class's package name. This location is customary, but not mandatory. The SEI class file may be located anywhere on the application classpath (see classpath description in item 1). When used, the SIB's @WebService.endpointInterface attribute's value must equal the complete name of this SEI.

  3. WSDL [optional] is contained in the META-INF/wsdl/ directory.

  4. ejb-jar.xml [optional] is contained in the META-INF/ directory.

  5. webservices.xml [optional] is contained in the META-INF/ directory.

  6. jax-ws-catalog.xml [optional] is contained in the META-INF/ directory. This descriptor is used in connection with OASIS XML Catalog 1.1 usage.

  7. sun-ejb-jar.xml [optional] is contained in the META-INF/ directory. This is the GlassFish-specific EJB deployment descriptor.

  8. Handler Chain Descriptor [optional] is contained under the / directory where it is available as a resource on the application classpath.

  9. Dependent Classes [optional] are contained in a separate JAR file at the root of the enclosing EAR where they will be available on the application classpath. These are any classes the SIB or SEI depends on. This is not a mandatory location. The dependent classes may be located anywhere on the application classpath (see classpath description in item 1).

Professional hosting         'Oracle Certified Expert Web Services Developer 6' Quiz     Free SCDJWS 5.0 Guide