Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/Development/Testing/DBWS"

(Test Automation)
(DBWS Server Tests)
 
(8 intermediate revisions by 2 users not shown)
Line 36: Line 36:
  
 
==== Test Automation ====
 
==== Test Automation ====
The tests in <code>eclipselink.dbws.test</code> and <code>eclipselink.utils.dbws.test</code> are run as part of the [http://www.eclipse.org/eclipselink/downloads/nightly.php nightly EclipseLink build process (on the servers at the Eclipse Foundation)]
+
The core DBWS tests and DBWSBuilder tests are run as part of the [http://www.eclipse.org/eclipselink/downloads/nightly.php nightly EclipseLink build process (on the servers at the Eclipse Foundation)]
  
 
It is possible to run the DBWS tests by manually invoking the appropriate ant targets:<br/>
 
It is possible to run the DBWS tests by manually invoking the appropriate ant targets:<br/>
1 In ...dbws/eclipselink.dbws.test<br/>
+
1 In ...<tt>dbws/eclipselink.dbws.test</tt><br/>
 
::<tt>prompt >ant build<br/>prompt >ant run-tests</tt><br/>The <tt>test.properties</tt> in the user's <tt>home</tt> directory will be used (since there is no <tt>test.properties</tt> file checked in to the SVN tree). The tests are specifically designed for MySQL, so the values should be something like:
 
::<tt>prompt >ant build<br/>prompt >ant run-tests</tt><br/>The <tt>test.properties</tt> in the user's <tt>home</tt> directory will be used (since there is no <tt>test.properties</tt> file checked in to the SVN tree). The tests are specifically designed for MySQL, so the values should be something like:
 
:::<tt>jdbc.driver.jar=path/to/mysql-connector-java-x.y.zz-bin.jar (currently x.y.zz = 5.1.13)
 
:::<tt>jdbc.driver.jar=path/to/mysql-connector-java-x.y.zz-bin.jar (currently x.y.zz = 5.1.13)
Line 50: Line 50:
 
:::logging.level=off &#35;'info' for light logging, 'fine' for SQL stmts, 'finest' for everything
 
:::logging.level=off &#35;'info' for light logging, 'fine' for SQL stmts, 'finest' for everything
 
</tt>
 
</tt>
The tests automatically setup and teardown the database resources required (table definitions, insert statments, stored procedures, etc.)
+
The tests automatically setup and teardown the database resources required (table definitions, insert statements, stored procedures, etc.)
  
2 In ...utils/eclipselink.utils.dbws<br/>
+
2 In ...<tt>utils/eclipselink.utils.dbws</tt><br/>
 
::<tt>prompt >ant build</tt><br/>switch over to test directory<br/><tt>prompt >cd ../eclipselink.utils.dbws.test</tt><br/><tt>prompt >ant run-tests</tt><br/>
 
::<tt>prompt >ant build</tt><br/>switch over to test directory<br/><tt>prompt >cd ../eclipselink.utils.dbws.test</tt><br/><tt>prompt >ant run-tests</tt><br/>
  
 
NB - The JUnit jar file should be on the classpath - Eclipse Helios GA uses 4.8.1, so a version compatible with that is preferable.
 
NB - The JUnit jar file should be on the classpath - Eclipse Helios GA uses 4.8.1, so a version compatible with that is preferable.
 +
 +
The results are generated to a <tt>reports</tt> directory - just open the <tt>junit-noframes.html</tt> file in a browser.
  
 
=== DBWS core tests ===
 
=== DBWS core tests ===
Line 413: Line 415:
 
=== End-to-end DBWS Web service testing ===
 
=== End-to-end DBWS Web service testing ===
 
The previous examples tested DBWS only in 'XR' mode. It is possible, however, to test a DBWS service {{:EclipseLink/Examples/DBWS/AdvancedJavase6Containerless}}
 
The previous examples tested DBWS only in 'XR' mode. It is possible, however, to test a DBWS service {{:EclipseLink/Examples/DBWS/AdvancedJavase6Containerless}}
 +
 +
== DBWS Server Tests ==
 +
See [http://wiki.eclipse.org/EclipseLink/Development/Testing/DBWS/2.5.0_Server_Tests 2.5.0 Server Tests]

Latest revision as of 12:26, 17 August 2012

Summary

DBWS has a number of test suites, all written using JUnit4. This page outlines the various testsuites and the types of testing in each suite.

DBWS test projects

In the EclipseLink SVN repository, there are a number of Eclipse projects that contain DBWS tests:

Eclipselink SVN Tree
\---trunk
    |   about.html
    |   ...
    +---dbws
    |   ...
    |   +---eclipselink.dbws.test
    |   |   ...
    |   +---etc
    |   |   dbsetup_nnn.sql
    |   |   dbteardown_nnn.sql
    |   ...
    |   +---eclipselink.dbws.test.oracle
    |   ...
    |
    \---utils
        |   ...
        +---eclipselink.utils.dbws.test
        |   ...
        +---eclipselink.utils.dbws.test.oracle
        |   ...

Database setup

The projects that end with .oracle are (obviously!) Oracle-specific; the others are designed to run on any database platform; however, the sql dbsetup/dbteardown DML in the etc directory is specific to MySQL 5. The method with the JUnit4 @BeforeClass annotation looks for database connectivity information in Java system properties:

-Ddb.driver=com.mysql.jdbc.Driver -Ddb.url=_some_db_url -Ddb.user=_some_db_user -Ddb.pwd=_some_db_password

Test Automation

The core DBWS tests and DBWSBuilder tests are run as part of the nightly EclipseLink build process (on the servers at the Eclipse Foundation)

It is possible to run the DBWS tests by manually invoking the appropriate ant targets:
1 In ...dbws/eclipselink.dbws.test

prompt >ant build
prompt >ant run-tests

The test.properties in the user's home directory will be used (since there is no test.properties file checked in to the SVN tree). The tests are specifically designed for MySQL, so the values should be something like:
jdbc.driver.jar=path/to/mysql-connector-java-x.y.zz-bin.jar (currently x.y.zz = 5.1.13)
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://<host>:<port(default is 3306)>/<database>
db.user=user
db.pwd=password
db.platform=org.eclipse.persistence.platform.database.MySQLPlatform
# Logging option for debugging
logging.level=off #'info' for light logging, 'fine' for SQL stmts, 'finest' for everything

The tests automatically setup and teardown the database resources required (table definitions, insert statements, stored procedures, etc.)

2 In ...utils/eclipselink.utils.dbws

prompt >ant build
switch over to test directory
prompt >cd ../eclipselink.utils.dbws.test
prompt >ant run-tests

NB - The JUnit jar file should be on the classpath - Eclipse Helios GA uses 4.8.1, so a version compatible with that is preferable.

The results are generated to a reports directory - just open the junit-noframes.html file in a browser.

DBWS core tests

The eclipselink.dbws.test project contains test classes that test DBWS in its XRM mode - no Web service deployment artifacts, no container -
just a bridge between OXM and ORM projects:

Eclipselink SVN Tree
\---trunk
    |   about.html
    |   ...
    |  
    +---dbws
    |   +---eclipselink.dbws.test
    |   |   |   .classpath
    |   |   |   .project
    |   |   |   build.properties
    |   |   |   build.xml
    |   |   |
    |   |   +---etc
    |   |   |       dbsetup_keymappings.sql
    |   |   |       dbsetup_relationships.sql
    |   |   |       dbteardown_keymappings.sql
    |   |   |       dbteardown_relationships.sql
    |   |   |
    |   |   \---src
    |   |       \---dbws
    |   |           \---testing
    |   |               |   DBWSTestHelper.java
    |   |               |   RootHelper.java
    |   |               |
    |   |               +---keymappings
    |   |               |       KeyMappingsTestSuite.java
    |   |               |
    |   |               \---relationships
    |   |                       RelationshipsAddress.java
    |   |                       RelationshipsEmployee.java
    |   |                       RelationshipsPhone.java
    |   |                       RelationshipsTestSuite.java


The setup required to run these tests is contained in the appropriately named dbsetup_xxx.sql/dbteardown_xxx.sql scripts
where xxx = keymappings or relationships).

The test code is in the (related) xxxTestSuite class - let's look at KeyMappingsTestSuite:

KeyMappingsTestSuite

public class KeyMappingsTestSuite {
 
    static final String KEYMAPPINGS_SCHEMA =
        "<?xml version='1.0' encoding='UTF-8'?>" +
        "<xsd:schema targetNamespace=\"urn:keymappings\" xmlns=\"urn:keymappings\" elementFormDefault=\"qualified\"\n" +
          "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
          ">\n" +
          "<xsd:complexType name=\"phone\">\n" +
...
    static final String KEYMAPPINGS_DBWS =
        "<?xml version='1.0' encoding='UTF-8'?>\n" +
        "<dbws\n" +
          "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
          "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
          "xmlns:ns1=\"urn:keymappings\"\n" +
          ">\n" +
          "<name>keymappings</name>\n" +
...
    static final String KEYMAPPINGS_OR_PROJECT =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
        "<object-persistence version=\"" + CONSTANT_PROJECT_BUILD_VERSION + "\"\n" +
          " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
          " xmlns=\"http://www.eclipse.org/eclipselink/xsds/persistence\"\n" +
          " >\n" +
           "<name>keymappings</name>\n" +
           "<class-mapping-descriptors>\n" +
              "<class-mapping-descriptor xsi:type=\"relational-class-mapping-descriptor\">\n" +
...
    static final String KEYMAPPINGS_OX_PROJECT =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
        "<object-persistence version=\"" + CONSTANT_PROJECT_BUILD_VERSION + "\"\n" +
           "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
           "xmlns=\"http://www.eclipse.org/eclipselink/xsds/persistence\"\n" +
           ">\n" +
           "<name>keymappings</name>\n" +
           "<class-mapping-descriptors>\n" +
              "<class-mapping-descriptor xsi:type=\"xml-class-mapping-descriptor\">\n" +
...
    // test fixtures
    public static XMLComparer comparer = new XMLComparer();
    public static XMLPlatform xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform();
    public static XMLParser xmlParser = xmlPlatform.newXMLParser();
    public static XRServiceAdapter xrService = null;
    @BeforeClass
    public static void setUp() {
        final String username = System.getProperty(DATABASE_USERNAME_KEY);
        if (username == null) {
            fail("error retrieving database username");
        }
Overriding behaviour

One of the notable things about this test class is the use of static Strings that contain all of the required XRM meta-data:
schema, ORM and OXM projects and the DBWS service descriptor file. For this test, these have been pre-built by hand and assembled
to follow the rules and styles of DBWS runtime processing. In fact, to be more accurate, these tests pre-date the existence of the
DBWSBuilder utility (that knows the rules and styles of DBWS runtime processing and produces meta-data to match).

We can see the static JUnit4 test fixtures for this testsuite: OX helper objects that will be used for comparing XML documents and an
xrService of type XRServiceAdapter. The XRServiceAdapter is a sub-class of XRServiceModel, the model object for the DBWS service descriptor
(fields: name, session-name and a Map<String, Operation> of operations). The XRServiceAdapter object has additional fields: schemaNamespace,
orSession (built from the ORM project), oxSession (built from the OXM project), xmlContext (built from the OXM project), schema and a
Map<QName, XMLDescriptor> of descriptorsByQName.

The XR service is built by an XRServiceFactory thru the API public XRServiceAdapter buildService(XRServiceModel xrServiceModel):

XRServiceFactory factory = new XRServiceFactory() {
    @Override
    public XRServiceAdapter buildService(XRServiceModel xrServiceModel) {
	parentClassLoader = this.getClass().getClassLoader();
	xrSchemaStream = new ByteArrayInputStream(KEYMAPPINGS_SCHEMA.getBytes());
	return super.buildService(xrServiceModel);
    }
 ...
};
XMLContext context = new XMLContext(new DBWSModelProject());
XMLUnmarshaller unmarshaller = context.createUnmarshaller();
DBWSModel model = (DBWSModel)unmarshaller.unmarshal(new StringReader(KEYMAPPINGS_DBWS));
xrService = factory.buildService(model);


The buildService method is overridden in the anonymous inner-class XRServiceFactory(){} because normally a XRServiceFactory looks for the
XRM meta-data artifacts in archive files (.jar, .war) on the classpath. In this case, the 'files' exist in-memory and can be directly built without doing
any classloader resource lookups (NB - the buildSessions method is overridden for the same reason - the OXM and ORM projects exist in-memory).

Invoking a DBWS operation

In the method getAllEmployees we can see how a DBWS query operation is invoked - an Invocation object is built with the same name as a
DBWS query operation described in the DBWS service descriptor file. Parameters may be added (in this specific case - get all employees - none are required)
and the xrService is used to execute the Invocation

Invocation invocation = new Invocation("getAllEmployees");
Operation op = xrService.getOperation(invocation.getName());
Object result = op.invoke(xrService, invocation);

The operation in this case returns a collection; thus, the result object must be cast to a Vector and each object marshalled to an XML document.
When the OR and OX projects were read in, a custom classloader builds any non-existent project model classes on-the-fly.

BaseEntityClassLoader becl = new BaseEntityClassLoader(parentClassLoader);
XMLContext context = new XMLContext(
    new EclipseLinkObjectPersistenceRuntimeXMLProject(), becl);
XMLUnmarshaller unmarshaller = context.createUnmarshaller();
Project orProject = (Project)unmarshaller.unmarshal(
    new StringReader(KEYMAPPINGS_OR_PROJECT));

Thus, the objects in the result Vector are all sub-classes of o.e.p.internal.dynamicpersist.BaseEntity

for (BaseEntity employee : resultVector) {
    rootHelper.roots.add(employee);
    rootHelper.roots.add(employee.get(0)); // address
    Vector<BaseEntity> phones = (Vector<BaseEntity>)employee.get(4); // phones
    phones.size(); // trigger IndirectList
    for (BaseEntity phone : phones) {
        rootHelper.roots.add(phone);
    }
}
Document doc = xmlPlatform.createDocument();
XMLMarshaller marshaller = xrService.getXMLContext().createMarshaller();
marshaller.marshal(rootHelper, doc);

In the OR-world, there is no problem with returning a graph of related or un-related classes in a single Vector. However, in the OX world, a document requires a
root element. Thus in the KEYMAPPINGS_OX_PROJECT there is a mapping for a helper class dbws.testing.RootHelper that uses the XMLAnyCollectionMapping
to allow either an Employee, or Address or Phone to be nested under the <employee-address-phone-system> element. Once the rootHelper is populated,
the xrService is used to marshall it to an XML document. Finally, the test fixtures xmlParser and comparer are used to indicate if the generated document
is the same as an expected control document:

Document controlDoc = xmlParser.parse(new StringReader(EMPLOYEE_COLLECTION_XML));
assertTrue("control document not same as XRService instance document",
    comparer.isNodeEqual(controlDoc, doc));
...
    public static final String EMPLOYEE_COLLECTION_XML =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        "<employee-address-phone-system xmlns=\"urn:keymappings\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
            "<employee address-ref-id=\"1\" employee-id=\"1\">" +
                "<first-name>Mike</first-name>" +
                "<last-name>Norman</last-name>" +
                "<phones>" +
                    "<phone-ref phone-id=\"1\"/>" +
                    "<phone-ref phone-id=\"2\"/>" +
                "</phones>" +
...

RelationshipsTestSuite

Structured in a similar fashion to KeyMappingsTestSuite, RelationshipsTestSuite is different in that it does not use a custom classloader to build classes
on the fly - the mapped domain classes actually exist. In addition, RelationshipsTestSuite demonstrates something that DBWSBuilder does not support:
mapping classes with 1:1 and 1:M relationships.

DBWS Utility tests

In the SVN repository under the Util component's high-level directory, there is a project eclipselink.utils.dbws.test This project contains test classes
that test the DBWSBuilder utility. As with the eclipselink.dbws.test tests, no Web service is deployed, the tests operate in XRM mode.

Eclipselink SVN Tree
\---trunk
    |   about.html
    |   ...
    |
    \---utils
        +---eclipselink.utils.dbws.test
        |   |   .classpath
        |   |   .project
        |   |   build.properties
        |   |   build.xml
        |   |
        |   +---etc
        |   |       dbsetup_attachedbinary.sql
        |   |       dbsetup_crud.sql
        |   |       dbsetup_customsql.sql
        |   |       dbsetup_inlinebinary.sql
        |   |       dbsetup_simplesp.sql
        |   |       dbsetup_simpletable.sql
        |   |       dbteardown_attachedbinary.sql
        |   |       dbteardown_crud.sql
        |   |       dbteardown_customsql.sql
        |   |       dbteardown_inlinebinary.sql
        |   |       dbteardown_simplesp.sql
        |   |       dbteardown_simpletable.sql
        |   |
        |   \---src
        |       \---dbws
        |           \---testing
        |               |   DBWSTestSuite.java
        |               |
        |               +---attachedbinary
        |               |       AttachedBinaryTestSuite.java
        |               |
        |               +---crud
        |               |       CRUDTestSuite.java
        |               |
        |               +---customsql
        |               |       CustomSQLTestSuite.java
        |               |
        |               +---inlinebinary
        |               |       InlineBinaryTestSuite.java
        |               |
        |               +---simplesp
        |               |       SimpleSPTestSuite.java
        |               |
        |               \---simpletable
        |                       SimpleTableTestSuite.java
        |


The setup required to run these tests is contained in the appropriately named dbsetup_xxx.sql/dbteardown_xxx.sql scripts (where xxx = attachedbinary, crud, customsql, inlinebinary,
simplesp or simpletable). The test code is in the (related) xxxTestSuite class - let's look at AttachedBinaryTestSuite:

AttachedBinaryTestSuite

public class AttachedBinaryTestSuite extends DBWSTestSuite {
 
    @BeforeClass
    public static void setUp() throws WSDLException {
        DBWS_BUILDER_XML_USERNAME =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<dbws-builder xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
              "<properties>" +
                "<property name=\"projectName\">attachedbinary</property>" +
                "<property name=\"targetNamespacePrefix\">ab</property>" +
                "<property name=\"logLevel\">off</property>" +
                "<property name=\"username\">";
        DBWS_BUILDER_XML_PASSWORD =
                "</property><property name=\"password\">";
        DBWS_BUILDER_XML_URL =
                "</property><property name=\"url\">";
        DBWS_BUILDER_XML_DRIVER =
                "</property><property name=\"driver\">";
        DBWS_BUILDER_XML_PLATFORM =
                "</property><property name=\"platformClassname\">";
        DBWS_BUILDER_XML_MAIN =
                "</property>" +
              "</properties>" +
              "<table " +
                "schemaPattern=\"%\" " +
                "tableNamePattern=\"attachedbinary\" " +
                ">" +
                "<procedure " +
                  "name=\"getBLOBById\" " +
                  "isCollection=\"false\" " +
                  "returnType=\"ab:attachedbinaryType\" " +
                  "procedurePattern=\"getBLOBById\" " +
                  "binaryAttachment=\"true\" " +
                "/>" +
              "</table>" +
            "</dbws-builder>";
        DBWSTestSuite.setUp();
    }
 
    public static SOAPAttachmentHandler attachmentHandler = new SOAPAttachmentHandler();


The DBWS_BUILDER_XML_xxx variables are static Strings that when assembled together, create a DBWSBuilder builder XML file. In the common setup code in DBWSTestSuite.setUp(), the strings are concatenated with the database properties:

...
    public static void setUp() throws WSDLException {
        String username = System.getProperty(DATABASE_USERNAME_KEY, DEFAULT_DATABASE_USERNAME);
        String password = System.getProperty(DATABASE_PASSWORD_KEY, DEFAULT_DATABASE_PASSWORD);
        String url = System.getProperty(DATABASE_URL_KEY, DEFAULT_DATABASE_URL);
        String driver = System.getProperty(DATABASE_DRIVER_KEY, DEFAULT_DATABASE_DRIVER);
        String platform = System.getProperty(DATABASE_PLATFORM_KEY, DEFAULT_DATABASE_PLATFORM);
        String builderString = DBWS_BUILDER_XML_USERNAME + username + DBWS_BUILDER_XML_PASSWORD +
            password + DBWS_BUILDER_XML_URL + url + DBWS_BUILDER_XML_DRIVER + driver +
            DBWS_BUILDER_XML_PLATFORM + platform + DBWS_BUILDER_XML_MAIN;

When the DBWSBuilder utility is invoked from the command-line, the builder XML file is parsed using a OXM project o.e.p.tools.dbws.DBWSBuilderModelProject; fortunately, this can be re-used for an in-memory string:

...
        XMLContext context = new XMLContext(new DBWSBuilderModelProject());
        XMLUnmarshaller unmarshaller = context.createUnmarshaller();
        DBWSBuilderModel builderModel =
            (DBWSBuilderModel)unmarshaller.unmarshal(new StringReader(builderString));
        builder.quiet = true;
        builder.setPlatformClassname(platform);
        builder.properties = builderModel.properties;
        builder.getProperties().put(SESSIONS_FILENAME_KEY, NO_SESSIONS_FILENAME);
        builder.operations = builderModel.operations;
        XRPackager xrPackager = new XRPackager() {
            @Override
            public void start() {// do nothing
            }
        };
        xrPackager.setSessionsFileName(builder.getSessionsFileName());
        xrPackager.setDBWSBuilder(builder);
        builder.setPackager(xrPackager);
        builder.build(DBWS_SCHEMA_STREAM, __nullStream, DBWS_SERVICE_STREAM, DBWS_OR_STREAM,
            DBWS_OX_STREAM, __nullStream, __nullStream, __nullStream, __nullStream, __nullStream,
            null);

An 'empty' custom o.e.p.tools.dbws.DBWSPackager is constructed and then finally, the build API is called with in-memory streams to capture all the generated DBWS and Web service artifacts.

See this page for more details about using the DBWSPackager class as a programmable API]]

End-to-end DBWS Web service testing

The previous examples tested DBWS only in 'XR' mode. It is possible, however, to test a DBWS service using Javase 6's 'containerless' javax.xml.ws.Endpoint API.

Javase 6 ships with the JAX-WS 2.x APIx inside the JDK - versions prior to update 4 have JAX-WS 2.0 APIs, which may cause some issues with later API requirements: to fix this, copy jaxws-api.jar and jaxb-api.jar into the endorsed directory (typically $JAVA_HOME/lib/endorsed or $JDK_HOME/jre/lib/endorsed). Please see this link for more details.

DBWSBuilder javase packager

When invoked from the command-line, the DBWSBuilder offers out-of-the-box support for building and packaging DBWS Services for either the WebLogic server or for running 'containerless' using the javax.xml.ws.Endpoint API

prompt > dbwsbuilder.cmd -builderFile {path_to_builder.xml} -stageDir {path_to_stageDir} -packageAs {packager}
Available packagers:
  -packageAs:[default=archive] wls [warFilename]
  -packageAs:[default=archive] javase [jarFilename]
                               ^^^^^^

Archive layout

The content of the .jar file is arranged differently from how the wls packager builds a .war file:

wls packager
    \---web-inf (root of .war file)
    |   web.xml
    |
    +---classes
    |   |
    |   +---META-INF
    |   |       eclipselink-dbws.xml
    |   |       eclipselink-dbws-or.xml
    |   |       eclipselink-dbws-ox.xml
    |   |       eclipselink-dbws-sessions.xml
    |   |
    |   \---_dbws
    |           DBWSProvider.class            -- auto-generated JAX-WS 2.0 Provider
    |
    \---wsdl
            eclipselink-dbws-schema.xsd
            eclipselink-dbws.wsdl
 
vs.
 
javase packager
    \---meta-inf (root of .jar file)
    |   eclipselink-dbws.xml
    |   eclipselink-dbws-or.xml
    |   eclipselink-dbws-ox.xml
    |   eclipselink-dbws-sessions.xml
    |
    +---wsdl
    |   eclipselink-dbws-schema.xsd
    |   eclipselink-dbws.wsdl
    |
    \---_dbws
        DBWSProvider.class

Generated Web service Provider

The code-generated _dbws.DBWSProvider class is annotated slightly differently for 'containerless' deployment:

package _dbws;
 
//javase imports
import java.lang.reflect.Method;
 
//java eXtension libraries
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.ServletContext;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import static javax.xml.ws.Service.Mode.MESSAGE;
 
//EclipseLink imports
import org.eclipse.persistence.internal.dbws.ProviderHelper;
 
@WebServiceProvider(
    /* wsdlLocation not present in @WebServiceProvider annotation for 'containerless' deployments */
    serviceName = "testService",
    portName = "testServicePort",
    targetNamespace = "urn:testService"
)
@ServiceMode(MESSAGE)
public class DBWSProvider extends ProviderHelper implements Provider<SOAPMessage> {
    public  DBWSProvider() {
        super();
    }
    @PostConstruct
    public void init() {
        super.init();
    }
    @Override
    public SOAPMessage invoke(SOAPMessage request) {
        return super.invoke(request);
    }
    @Override
    @PreDestroy
    public void destroy() {
        super.destroy();
    }
...
}

Example

For a DBWS service based on a DBWSBuilder table query operation:

<?xml version="1.0" encoding="UTF-8"?>
<dbws-builder xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <properties>
    <property name="projectName">emp</property>
    ...
  </properties>
  <table
    catalogPattern="%"
    tableNamePattern="EMP"
  />
</dbws-builder>

With the .jar on the classpath, an Endpoint can be created programmatically:

//javase imports
...
import static javax.xml.ws.BindingProvider.ENDPOINT_ADDRESS_PROPERTY;
import static javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING;
...
//domain imports
import _dbws.DBWSProvider;
 
public class ContainerlessTest {
 
    static final String ENDPOINT_ADDRESS = 
        "http://localhost:9999/test";
 
    public static void main(String[] args) {
 
        // build Endpoint
        Endpoint endpoint = Endpoint.create(new DBWSProvider());
        endpoint.publish(ENDPOINT_ADDRESS);
 
        // retrieve info from Provider's annotations
        WebServiceProvider dbwsProvider = DBWSProvider.class.getAnnotation(WebServiceProvider.class);
        String serviceNamspace = dbwsProvider.targetNamespace();
        String serviceName = dbwsProvider.serviceName();
        String portName = dbwsProvider.portName();
 
        // build service
        QName serviceQName = new QName(serviceNamspace, serviceName);
        QName portQName = new QName(serviceNamspace, portName);
        Service testService = Service.create(serviceQName);
        testService.addPort(portQName, SOAP11HTTP_BINDING, ENDPOINT_ADDRESS);
 
        // build dispatch to send SOAP msg
        Dispatch<SOAPMessage> dispatch = testService.createDispatch(portQName, SOAPMessage.class,
            Service.Mode.MESSAGE);
        BindingProvider bp = (BindingProvider)dispatch;
        Map<String, Object> rc = bp.getRequestContext();
        rc.put(ENDPOINT_ADDRESS_PROPERTY,ENDPOINT_ADDRESS);
 
        MessageFactory factory = MessageFactory.newInstance();
        SOAPMessage request = factory.createMessage();
        SOAPPart part = request.getSOAPPart();
        DOMSource domSource = new DOMSource(db.parse(
            new InputSource(new StringReader(FIND_BY_PK_REQUEST))));
        part.setContent(domSource);
        SOAPMessage response = null;
        try {
            response = dispatch.invoke(request);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        if (response != null) {
            Source src = response.getSOAPPart().getContent();
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            DOMResult result = new DOMResult();
            transformer.transform(src, result);
            Document resultDoc = (Document)result.getNode();
            System.out.print(documentToString(resultDoc));
        }
 
        // tearDown service
        endpoint.stop();
    }
 
    static final String FIND_BY_PK_REQUEST =
        "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
          "<env:Body>" +
            "<ns1:findByPrimaryKey_empType xmlns:ns1=\"urn:testService\" xmlns=\"urn:test\">" +
               "<ns1:id>7369</ns1:id>" +
            "</ns1:findByPrimaryKey_empType>" +
          "</env:Body>" +
         "</env:Envelope>";
 
    static String documentToString(Document doc) {
        DOMSource domSource = new DOMSource(doc);
        StringWriter stringWriter = new StringWriter();
        StreamResult result = new StreamResult(stringWriter);
        try {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty("indent", "yes");
            transformer.transform(domSource, result);
            return stringWriter.toString();
        } catch (Exception e) {
            // e.printStackTrace();
            return "<empty/>";
        }
    }   
}

Result:

<?xml version="1.0">
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header />
  <SOAP-ENV:Body>
    <srvc:findByPrimaryKey_empTypeResponse xmlns="urn:test" xmlns:srvc="urn:testService">
      <srvc:result>
        <empType>
          <empno>7369</empno>
          <ename>SMITH</ename>
          <job>CLERK</job>
          <mgr>7902</mgr>
          <hiredate>1980-12-17T00:00:00.0-05:00</hiredate>
          <sal>800</sal>
          <deptno>20</deptno>
        </empType>
      </srvc:result>
    </srvc:findByPrimaryKey_empTypeResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


DBWS Server Tests

See 2.5.0 Server Tests

Back to the top