WS-JEE is minuteproject track to quickly have a webservice based on JAX-WS on top of a backend with JPA2 layer.
This page goes through:

You can generate the code against you DB model via minuteproject console or through configuration. For that, download MinuteProjectlast version.

For the rest of the page will deal with the code generated from the demo application.
You can have the resulting source if you download demo-src-generated-x.y.z.zip
Or you can generate by running /demo/config/all-demos.(cmd/sh), see Demos.


Operating principle

This diagram resumes how MinuteProject works in the context of code generation for Webservices JEE application that is ultimately deployed on Glassfish.
The glassfish server used is 3.1.1.b08 bundled with Netbeans 7.0.1 RC1

WS-JEE-glassfish.jpg

Configuration

Here is the main configuration dealing the model enrichment and the load of the Webservices JEE target templates.
<!DOCTYPE root>
<generator-config>
    <configuration>
        <conventions>
            <target-convention type="enable-updatable-code-feature" />
        </conventions>
        <model name="petshop" version="1.0" package-root="net.sf.mp.demo">
            <data-model>
                <dataSource>
                    <driverClassName>org.hsqldb.jdbcDriver</driverClassName>
                    <url>jdbc:hsqldb:hsql://127.0.0.1:9001/petshop</url>
                    <username>sa</username>
                    <password></password>
                </dataSource>
                <!-- for Oracle and DB2 please set the schema
                <schema> </schema>
                 -->
                <primaryKeyPolicy oneGlobal="true" oneForEachTable="false">
                    <primaryKeyPolicyPattern prefix="" suffix="" name="sequencePattern" sequenceName="hibernate_sequence"></primaryKeyPolicyPattern>
                </primaryKeyPolicy>
            </data-model>
            <business-model>
                <generation-condition>
                    <condition type="exclude" startsWith="DUAL"></condition>
                    <condition type="exclude" startsWith="ID_GEN"></condition>
                </generation-condition>
                <business-package default="pet">
                    <condition type="package" startsWith="PRODUCT" result="product"></condition>
                    <condition type="package" startsWith="ITEM" result="product"></condition>
                </business-package>
                <enrichment>
                   <conventions>
                      <entity-naming-convention type="apply-strip-table-name-prefix" pattern-to-strip="SYS,FIN"/>
                      <column-naming-convention type="apply-fix-primary-key-column-name-when-no-ambiguity" default-value="ID"/>
                      <reference-naming-convention type="apply-referenced-alias-when-no-ambiguity" is-to-plurialize="true"></reference-naming-convention>
                   </conventions>
                    <package name="product">
                        <entity-group entities="PRODUCT"></entity-group>
                        <entity-group entities="ITEM"></entity-group>
                    </package>
                    <entity name="PRODUCT" alias="MY_GOOD_PRODUCT">
                    </entity>
                    <entity name="ITEM" alias="MY_GOOD_ITEM" comment="my item table">
                        <field name="PRODUCTID" alias="THIS_IS_MY_PRODUCT" comment="my product field reference"></field>
                    </entity>
                    <entity name="CATEGORY" content-type="reference-data" >
                       <semantic-reference>
                         <sql-path path="NAME"/>
                       </semantic-reference>
                    </entity>
                </enrichment>
            </business-model>
        </model>
        <targets catalog-entry="WS-JEE"/>
    </configuration>
</generator-config>
The main oustanding points dealing with WebService JEE are:
  • <property name="use-temporal" value="true"/>
    • indicates to use Temporal annotation instead of java.sql.Timestamp/Date. It is useful since Timestamp does not have a no-arg constructor.
  • <entity name="TAG_ITEM" master-relationship-field="ITEMID"/>
    • The TAG_ITEM table is use for a ManyToMany relationship and nothing is generated as a JPA2 entity.
    • Meanwhile when it is relevant, setting the master of the relationship indicates the owner (entity) of the information.
      • Here ITEM table is the owner
  • <property name="add-xmlbinding" value="true">
    • Means that JPA2 template must add JAXB annotations
  • <property name="add-xml-format" value="lowercase-hyphen">
    • Means that JAXB element name will be in lowercase and the separator is an hyphen (-).
    • Other format are java-variable, uppercase-underscore, java-class
  • <target name="WS-JEE-ejb" ...
    • Indicates to create a pom project for the EJB Webservice with CDI.
  • <target name="WS-JEE-war" ...
    • Indicates to create a pom project to package the artifacts in a war.
  • <target-convention type="enable-updatable-code-feature" />
    • Indicates that the generated artifacts are updatable when the templates have an updatable nature (see Customisation).

Generation

Prequisites

Have Java 6 setup.
Download MinuteProjectlast version.

Ensure that you have the petshop database running.
/sample/start-petshop-database.(cmd/sh)

Run demo-WS-JEE.(cmd/sh) in /demo/config.

Resulting artifacts


MinuteProject 4 WS-JEE generates 4 maven pom project structure are generated
  • JPA2 backend maven project (see JPA2 for details regarding jpa2 annotations, see below for some explanation about jaxb annotations)
  • EJB3 webservice access maven on top of backend
  • web maven project packaging
  • global maven pom project
WS-JEE-generated-pom-structure.png

The maven EJB3 project contains the following artifacts.
  • web.xml
  • beans.xml for dependency injection
  • stateless EJB3 for Webservice for each entity
  • stateless EJB3 for Webservice for the entire model
  • EJB3 for DAO one per entity
  • pom.xml for JEE integration
WS-JEE-EJB3-Webservice-pom.png

Application Code

PetshopWebService will give the webservice entry point for the model via JAX-WS annotation and offers CRUD operations.
Once deployed this class will give a WSDL entry point. On glassfish JEE server, metro will generated dynamically the WSDL content.
The EJB are injected via CDI.
The code contains added areas tagged by MP-MANAGED-ADDED-AREA-BEGINNING and MP-MANAGED-ADDED-AREA-ENDING to add your own code.
package net.sf.mp.demo.petshop.ws.impl;
 
//MP-MANAGED-ADDED-AREA-BEGINNING @import@
//MP-MANAGED-ADDED-AREA-ENDING @import@
...
 
@WebService(endpointInterface = "net.sf.mp.demo.petshop.ws.impl.PetshopWebService"
           ,serviceName="PetshopWebService")
public class PetshopWebService {
 
 
    @Inject
    private AddressDaoEJB addressDaoEJB;
    @Inject
    private CategoryDaoEJB categoryDaoEJB;
    @Inject
    private SellercontactinfoDaoEJB sellercontactinfoDaoEJB;
    @Inject
    private TagDaoEJB tagDaoEJB;
    @Inject
    private ZiplocationDaoEJB ziplocationDaoEJB;
    @Inject
    private MyGoodItemDaoEJB myGoodItemDaoEJB;
    @Inject
    private MyGoodProductDaoEJB myGoodProductDaoEJB;
 
    public List<Address> findAllAddress (Address address) {
        return addressDaoEJB.findAll(address);
    }
 
    public Address findAddressById (java.lang.Integer id) {
        return addressDaoEJB.find(id);
    }
 
    public Address createAddress (Address address) {
        return addressDaoEJB.create(address);
    }
...
//MP-MANAGED-ADDED-AREA-BEGINNING @implementation@
//MP-MANAGED-ADDED-AREA-ENDING @implementation@
}
 
AddressDaoEJB
package net.sf.mp.demo.petshop.dao.impl.pet;
 
//MP-MANAGED-ADDED-AREA-BEGINNING @import@
//MP-MANAGED-ADDED-AREA-ENDING @import@
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
 
import javax.annotation.Resource;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.transaction.UserTransaction;
 
import net.sf.mp.demo.petshop.pet.Address;
/**
 *
 * <p>Title: AddressDaoEJB</p>
 *
 * <p>Description: remote interface for AddressDaoEJB service </p>
 *
 */
 
@Stateless public class AddressDaoEJB  {
 
    @PersistenceContext(unitName = "petshop")
    private EntityManager em;
 
    public List<Address> findAll (Address address) {
        Query query = em.createQuery("select address from Address address");
        return query.getResultList();
    }
 
    public List<Address> findAll () {
        Query query = em.createQuery("select address from Address address");
        return query.getResultList();
    }
 
    public Address findById (java.lang.Integer id) {
        return em.find (Address.class, id);
    }
 
    public Address find (java.lang.Integer id) {
        Query query = em.createQuery("select address from Address address where address.id = :id");
        query.setParameter("id", id);
        List list = query.getResultList();
        if (list!=null && !list.isEmpty()) {
            Address var = (Address)list.get(0);
            return var.flat();
        }
        return new Address();
    }
 
    public Address create (Address address) {
        em.persist (address);
        return address;
    }
 
    public Address update (Address address) {
        em.merge (address);
        return address;
    }
 
    public void delete (Address address) {
        if (address.getId()!=null)
            em.remove (findById(address.getId()));
    }
 
//MP-MANAGED-ADDED-AREA-BEGINNING @implementation@
//MP-MANAGED-ADDED-AREA-ENDING @implementation@
}



Packaging-deployment

Packaging

On /output/WS-JEE/petshop run:
mvn package
It will create the
  • JPA2 backend
  • EJB3 WebService API
  • War package

The result app war petshopWebServiceApp.war is in /output/WS-JEE/petshop/WS/target.

Deployment

Start glassfish (Tested on 3.1.1.b08 bundled with Netbeans 7.0.1 RC1).

Check jdbc/petshopDS Datasource is configured.
Deploy App:
  • by console
  • by command line asadmin deploy --force=true WS-JEE\target\petshopWebServiceApp.war

Testing


The wsdl is located at http://localhost:8080/petshopWebServiceApp/PetshopWebService?wsdl
It contains the CRUD service for all the entities of the model.
Once deployed the application application can be tested by SOAPUI.
This is what you can get when you open the wsdl as a SOAPUI project.

WS-JEE-soapui-findbyId-sample.png


Customisation

Since Release 0.6 MinuteProject has a new feature called Updatable Generated Code.
In the context of WS-JEE it enables you to change artifacts generated in:
  • JPA2 Layer
  • EBJ3 layer
  • WebService
This feature enables the developer for instance to add new methods in the WebService artifact (PetshopWebService.java) on one side and to modify its DB structure on the other.
In the next generation MinuteProject will add the new CRUD operation for the new entities and also preserves the developer new methods.

Knowledge sources


http://www.redstream.nl/2009/02/11/create-a-ejb3-webservice-with-maven2-running-on-glassfish/

http://weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0