With the advent of Java EE 5, Enterprise Beans can act as Web-Service components and since Java EE 6 they may be packaged within a WAR module as Java programming language class files. Java EE based web services come in two flavours: JAX-WS and JAX-RS. This tutorial examines JAX-WS and EJB 3.1.


The Java EE 6 specifications include JAX-WS as one of its technologies. JAX-WS is the standard way to develop SOAP (Simple Object Access Protocol) web services in the Java platform. The JAX-WS Reference Implementation, included in GlassFish distributions, is Metro, a Web Services framework that provides tools and infrastructure to develop Web Services solutions. This tutorial  demonstrates how to create a JAX-WS application based on  stateless session EJBs with GlassFish Server and Eclipse for Java EE developers. A sample application is provided too.

Downloading, Installing, and Configuring Required Software

Before you begin, download, install, and configure the required software.

  1. Ensure that Java Development Kit (JDK) 6 is installed and that paths and environment variables for the JDK are correct. If the JDK and the Java Runtime Environment (JRE) are installed, ensure that the path to the JDK precedes the path to the JRE in your path statement. Otherwise, GlassFish Server might use a JRE for its Java virtual machine (VM) and steps for compiling JavaServer Pages (JSP) technology pages will fail.
  2. Download and install Eclipse IDE for Java EE developers.
  3. Download and install GlassFish Server Open Source Edition 3.1.2.
  4. Download and install the GlassFish Server plugin for Eclipse IDE. When you add an update site, specify the location as http://download.java.net/glassfish/eclipse/indigo and not the location that is stated in the instructions.
  5. Register your installation of GlassFish Server with Eclipse IDE. When you select the server type, select GlassFish 3.1.2 and not the type that is stated in the instructions.
  6. Change the global preferences for GlassFish Server to meet the requirements of your application. If your application uses the Java DB database that is bundled with GlassFish , select all options on the Preferences page as shown in the following figure.       

Cannot resolve external resource into attachment.

Setting Up the Database and Data Source

Exactly how to set up the database and data source depends on the database that your application uses. For detailed instructions, see Administering Database Connectivity in Oracle GlassFish Server Administration Guide.

Modifying the DerbyPool Connection Pool

The sample application uses the preconfigured DerbyPool connection pool for connections to the database. To enable the sample application to use this pool, you must modify the preset values of some properties of the pool.

Before you begin, ensure that the option to start the Java DB process with GlassFish Server is set in the global preferences for the GlassFish Server.

  1. Start GlassFish Server in Eclipse IDE. The JavaDB database that is bundled with GlassFish Server is also started.
  2. In the Servers view, select and right-click GlassFish Server.
  3. From the pop-up menu that opens, choose GlassFish→View Admin Console. The GlassFish Server Administration Console is opened in the system browser.
  4. In the navigation tree, under the Resources node, expand the JDBC node.
  5. Under the JDBC node, select the JDBC Connection Pools node. The Connection Pools page opens.
  6. In the table of connection pools, click DerbyPool. The Edit Connection Pool page opens.
  7. On the Edit Connection Pool page, click the Additional Properties tab. The Edit Connection Pool Properties page opens.
  8. Edit the properties as follows:
    Property Value
    User user
    Password user
    DatabaseName newdb

    The following figure shows the Edit Connection Pool Properties page after these properties have been edited. Cannot resolve external resource into attachment.

  1. Click Save.
  2. Confirm that the connection to the pool is usable.
    1. On the Edit Connection Pool Properties page, click the General tab. The Edit Connection Pool page opens.
    2. On the Edit Connection Pool page, click Ping.
  3. Confirm that the JNDI name of the connection pool is correct.
    1. In the navigation tree, under the Resources node, expand the JDBC node.
    2. Under the JDBC node, select the JDBC Resources node. The JDBC Resources page opens.

On the JDBC Resources page, select jdbc/__default. DerbyPool is associated with this JNDI name as shown in the following figure.

  Cannot resolve external resource into attachment.

Sample Application overview

The sample application consists of two parts: a "server" application (web service provider) and a "client" application (web service consumer).

  • The client application allows an end-user to enter the name of a customer. It's a simple form that invokes a basic servlet to process the data. The web tier accesses a session bean which implements the business logic (adding an application specific id to the customer). The session bean also acts as a web service consumer sending a SOAP message (the name of the customer with the application-specific id) to the server.
  • The server application is a session bean which receives the SOAP message and saves it to a RDBMS using a Java persistence entity. The entity accesses the database table that store the entity states. A plain old Java object (POJO) with some annotations specifies how JPA is to store the data persistently.

You can read more about the JAX-WS 2.2 standard at jax-ws.java.net , about the SOAP standard at www.w3.org, about the JPA standard at Java EE6 tutorial.

To Convert the Sample Application to an Eclipse IDE Project

The sample application is distributed as a two web application archive (WAR) files. To use this applications, you must convert them to Eclipse IDE projects.

  1. Download the server and the client application WAR file (ServerWS-web.war and ClientWS-web.war).
  2. Import the application WAR files into Eclipse IDE.

The server application

As of new EE6 specifications, stateless, stateful and singleton session beans can be used as web service provider. An EJB no longer requires a local business interface: it may expose a no-interface view. EJB's packaging has changed too. Enterprise beans, often providing the business logic of a web application or in this case of a web service, may be packaged within a WAR module as Java programming language class files or within a JAR file that is bundled within the WAR module.

  1. Even with EJBs, this is a dynamic web project in Eclipse.
  2. In the source folder of this project, there's a META-INF directory with the persistence.xml file. The application uses the JavaDB database, with Glassfish Server. By default, GlassFish Server Open Source Edition uses EclipseLink as the persistence provider and it controls transactions by using the using the jdbc/_default DataSource object. This object is specified in the jta-data-source element of the persistence.xml file as follows:
    <jta-data-source>jdbc/__default</jta-data-source>
  3. The @LocalBean annotation denotes a no-interface ejb and the class, a stateless session bean, also needs to be decorated with the @Stateless and @WebService annotations. Session bean's public methods are exposed through the @WebMethod annotation:
    @LocalBean
    @Stateless
    @WebService
    public class CustomerServiceBean {
    
    	@PersistenceContext(unitName="CustomerService")
    	   private EntityManager em;
    
    	   @WebMethod
    	    public String addCustomer(Customer customer) throws  InvalidCustomerException{
    		   if(customer.getFirstName().length() == 0)
    	        	throw new InvalidCustomerException("The Customer" +" firstname cannot be empty. Please specify a name for the item. ");
    	        if(customer.getLastName().length() == 0)
    	        	throw new InvalidCustomerException("The Customer" +" lastname cannot be empty. Please specify a name for the item. ");
    	        em.persist(customer);
    	        return "Customer added";
    	    }
    
    }

To Run the Server Application

  1. In the Project Explorer view, select and right-click the ServerWS-web project.
  2. From the pop-up menu that opens, select Run As→Run on Server. The Run on Server wizard opens.
  3. Ensure that the option to choose an existing server is selected.
  4. From the list of servers, select GlassFish Server and click Next. The Add and Remove page opens.
  5. Confirm that ServerWS-web is listed under the configured projects.
  6. Click Finish.

You don't need to run the command wsgen. From JAX-WS RI 2.1.4 onwards the runtime takes care of it by generating these classes and the WSDL (available at "http://localhost:8080/CustomerServiceBeanService/CustomerServiceBean?wsdl") file dynamically.

The client application

  1. The package ee.endpoint is automatically generated. If you don't import the provided Web Archive file ClientWS-web.war into Eclipse you need to run the wsimport command:
    1. In the project's source folder open a shell prompt and run the command: "wsimport -keep -verbose http://localhost.localdomain:8080/CustomerServiceBeanService/CustomerServiceBean?wsdl". This tool generates JAX-WS portable artifacts that can be packaged in a WAR file with the WSDL and schema documents along with the web service consumer to be deployed.
  2. The WebServiceRef annotation in ClientEjbBean class  is used to define a reference to the server application with a URL pointing to the WSDL document for the web service provider.
    @Stateless
    @LocalBean
    
    public class ClientEjbBean {
    
    	@WebServiceRef(wsdlLocation = "http://localhost.localdomain:8080/CustomerServiceBeanService/CustomerServiceBean?wsdl")
        private CustomerServiceBeanService service;
    
       public ClientEjbBean() {
           // TODO Auto-generated constructor stub
       }
    
       public String invokeWS(Customer customer) throws InvalidCustomerException_Exception {
    	   //business method
    	   // it adds a business code to the customer
           		customer.setAppCode(new Long(1234567));
    			return this.addCustomer(customer);
       }
    
       private String addCustomer(ee.endpoint.Customer arg0) throws InvalidCustomerException_Exception {
    	   ee.endpoint.CustomerServiceBean port = service.getCustomerServiceBeanPort();
           return port.addCustomer(arg0);
       }
    
    }
  3. The Class InvalidCustomerException_Exception (automatically generated) refers to a fault element in the SOAP message. In the server application the web service ejb throws a Java checked exception. Since checked exceptions don't exist in the SOAP protocol, InvalidCustomerException_Exception is not an exception type at all, but a regular bean that acts as a holder for the SOAP Fault information: it uses the @WebFault annotation and extends Exception.
    @WebFault(name = "InvalidCustomerException", targetNamespace = "http://endpoint.ee/")
    public class InvalidCustomerException_Exception
        extends Exception
    {
    
        /**
         * Java type that goes as soapenv:Fault detail element.
         *
         */
        private InvalidCustomerException faultInfo;
    
        /**
         *
         * @param message
         * @param faultInfo
         */
        public InvalidCustomerException_Exception(String message, InvalidCustomerException faultInfo) {
            super(message);
            this.faultInfo = faultInfo;
        }
    
        /**
         *
         * @param message
         * @param faultInfo
         * @param cause
         */
        public InvalidCustomerException_Exception(String message, InvalidCustomerException faultInfo, Throwable cause) {
            super(message, cause);
            this.faultInfo = faultInfo;
        }
    
        /**
         *
         * @return
         *     returns fault bean: ee.endpoint.InvalidCustomerException
         */
        public InvalidCustomerException getFaultInfo() {
            return faultInfo;
        }
    
    }
  4. The Customer object (automatically generated) represents the XML content of the SOAP message. This java class is converted to an XML format by JAXB. JAXB provides the ability to marshal Java objects into XML and the inverse: it binds Java method signatures and WSDL messages and operations.
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "customer", propOrder = {
        "appCode",
        "firstName",
        "id",
        "lastName"
    })
    public class Customer {
    
        protected Long appCode;
        protected String firstName;
        protected Long id;
        protected String lastName;
    
        /**
         * Gets the value of the appCode property.
         *
         * @return
         *     possible object is
         *     {@link Long }
         *
         */
        public Long getAppCode() {
            return appCode;
        }
    
        /**
         * Sets the value of the appCode property.
         *
         * @param value
         *     allowed object is
         *     {@link Long }
         *
         */
        public void setAppCode(Long value) {
            this.appCode = value;
        }
    
        /**
         * Gets the value of the firstName property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getFirstName() {
            return firstName;
        }
    
        /**
         * Sets the value of the firstName property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setFirstName(String value) {
            this.firstName = value;
        }
    
        /**
         * Gets the value of the id property.
         *
         * @return
         *     possible object is
         *     {@link Long }
         *
         */
        public Long getId() {
            return id;
        }
    
        /**
         * Sets the value of the id property.
         *
         * @param value
         *     allowed object is
         *     {@link Long }
         *
         */
        public void setId(Long value) {
            this.id = value;
        }
    
        /**
         * Gets the value of the lastName property.
         *
         * @return
         *     possible object is
         *     {@link String }
         *
         */
        public String getLastName() {
            return lastName;
        }
    
        /**
         * Sets the value of the lastName property.
         *
         * @param value
         *     allowed object is
         *     {@link String }
         *
         */
        public void setLastName(String value) {
            this.lastName = value;
        }
    
    }
  5. To run the client application, follow the same steps as the server application.

Further Reading

For more information about the technologies in this tutorial, see the following documentation: