You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2019/01/21 12:19:18 UTC

[tomee] branch master updated: Add README.adoc to applicationcomposer-jaxws-cdi/ - TOMEE-2370

This is an automated email from the ASF dual-hosted git repository.

jgallimore pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee.git


The following commit(s) were added to refs/heads/master by this push:
     new cdbf507  Add README.adoc to applicationcomposer-jaxws-cdi/ - TOMEE-2370
     new 138993f  Merge pull request #379 from BogdanStirbat/TOMEE-2370
cdbf507 is described below

commit cdbf507b26a0f13d45e0aa58f75b36cd2d9c0cc2
Author: Bogdan Stirbat <bo...@gmail.com>
AuthorDate: Sat Jan 19 18:48:23 2019 +0200

    Add README.adoc to applicationcomposer-jaxws-cdi/ - TOMEE-2370
---
 examples/applicationcomposer-jaxws-cdi/README.adoc | 232 +++++++++++++++++++++
 .../superbiz/example/jaxws/MeetingPlannerTest.java |  46 +++-
 2 files changed, 271 insertions(+), 7 deletions(-)

diff --git a/examples/applicationcomposer-jaxws-cdi/README.adoc b/examples/applicationcomposer-jaxws-cdi/README.adoc
new file mode 100644
index 0000000..07421ff
--- /dev/null
+++ b/examples/applicationcomposer-jaxws-cdi/README.adoc
@@ -0,0 +1,232 @@
+= Application Composer with JAX-WS and CDI
+:index-group: Testing Techniques
+:jbake-type: page
+:jbake-status: published
+
+This example shows the use of `@ApplicationComposer` annotation, in the context of a JAX-WS application.
+
+Application Composer is an API for creating an EE application programmatically. It is very useful in a text context, so it's no wonder that it originated from here.
+For more information about Application Composer, please refer to http://tomee.apache.org/tomee-8.0/docs/application-composer/index.html[Application Composer section in the documentation].
+In this example, we will use `@ApplicationComposer` in the context of a JAX-WS application.
+
+== Example
+
+This example is a meeting planner application. It is a JAX-WS application, and it accepts incoming booking meeting requests. The application first checks if the request can be booked, books it if possible,
+and returns to the caller if the request was booked (a boolean value). This is a simple, demo-purpose application, so it is greatly simplified. A book request is represented only by the meeting start date (a `java.util.Date` value).
+A book request is bookable if it starts after current date.
+
+The business logic is implemented using a `MeetingPlannerImpl` class (implementing `MeetingPlanner`). This class is a JAX-WS service, exposing the following method: `boolean book(final Date date)`.
+The client will send a request, containing a date; the service will return if the request can be booked, true or false. The exposed JAX-WS service uses in addition a different feature, CDI, injecting a
+business logic service class checking if the request is bookable. So, when the time will come to test the `@ApplicationComposer` annotation, we will both check that CDI worked in our programmatically
+started application and that the JAX-WS service is up and running.
+
+The business logic that checks if a request is bookable is defined by the following interface:
+
+....
+import java.util.Date;
+
+public interface Agenda {
+    boolean isBookable(Date d);
+}
+....
+
+The implementation is a simple one, without distracting details:
+
+....
+import java.util.Date;
+
+public class LazyAgenda implements Agenda {
+    @Override
+    public boolean isBookable(final Date d) {
+        return d.after(new Date());
+    }
+}
+....
+
+The JAX-WS service is defined by the following interface:
+
+....
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+import java.util.Date;
+
+@WebService
+public interface MeetingPlanner {
+
+    @WebMethod(operationName = "book", exclude = false)
+    boolean book(final Date date);
+}
+....
+
+The class implementing this interface is:
+
+....
+import javax.inject.Inject;
+import javax.jws.WebService;
+import java.util.Date;
+
+@WebService
+public class MeetingPlannerImpl implements MeetingPlanner {
+    @Inject
+    private Agenda agenda;
+
+    @Override
+    public boolean book(final Date date) {
+        return agenda.isBookable(date);
+    }
+}
+....
+
+== Using Application Composer
+
+Now, that the application is completed, it's time to test it. For this, we will add a unit test that will use Application Composer to start and deploy our application in a full JEE environment.
+The full test:
+
+....
+import org.apache.openejb.jee.WebApp;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.Configuration;
+import org.apache.openejb.testing.EnableServices;
+import org.apache.openejb.testing.Module;
+import org.apache.openejb.testng.PropertiesBuilder;
+import org.apache.openejb.util.NetworkUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.namespace.QName;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.Service;
+import java.net.URL;
+import java.util.Date;
+import java.util.Properties;
+
+import static org.junit.Assert.assertTrue;
+
+@EnableServices("jax-ws")
+@RunWith(ApplicationComposer.class)
+public class MeetingPlannerTest {
+    private static final int JAX_WS_PORT = NetworkUtil.getNextAvailablePort();
+
+    @Configuration
+    public Properties configuration() {
+        return new PropertiesBuilder().p("httpejbd.port", Integer.toString(JAX_WS_PORT)).build();
+    }
+
+    @Module
+    @Classes(cdi = true, value = {MeetingPlannerImpl.class, LazyAgenda.class})
+    public WebApp war() {
+        return new WebApp()
+                .contextRoot("/demo")
+                .addServlet("jaxws", MeetingPlannerImpl.class.getName(), "/meeting-planner");
+    }
+
+    @Test
+    public void bookPort() throws Exception {
+        final Service service = Service.create(
+                new URL("http://127.0.0.1:" + JAX_WS_PORT + "/demo/meeting-planner?wsdl"),
+                new QName("http://jaxws.example.superbiz.org/", "MeetingPlannerImplService"));
+        final MeetingPlanner planner = service.getPort(MeetingPlanner.class);
+        assertTrue(planner.book(new Date(System.currentTimeMillis() + 1000000)));
+    }
+}
+....
+
+First thing to see, we use Application Composer as a JUnit runner. So, our test integrates with current tools just like any other JUnit test. The test's configuration is defined in the method annotated with `@Configuration`.
+
+The application is started in the method having the `@Module` annotation. In this example, we specify the classes we want to scan, and the fact that we want to use CDI.
+
+Our test makes a booking request, sending a date in the future, then it verifies that booking is done.
+
+== Running the test
+
+Running the test we can see that the application was successfully started, that the JAX-WS service is running and that it fulfills incoming requests correctly.
+
+....
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.example.jaxws.MeetingPlannerTest
+INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@49993335
+INFO - Succeeded in installing singleton service
+INFO - Cannot find the configuration file [conf/openejb.xml].  Will attempt to create one for the beans deployed.
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Creating TransactionManager(id=Default Transaction Manager)
+INFO - Creating SecurityService(id=Default Security Service)
+INFO - Initializing network services
+INFO - Creating ServerService(id=cxf)
+INFO - Creating ServerService(id=httpejbd)
+INFO - Created ServicePool 'httpejbd' with (10) core threads, limited to (200) threads with a queue of (9)
+INFO - Initializing network services
+INFO -   ** Bound Services **
+INFO -   NAME                 IP              PORT
+INFO -   httpejbd             127.0.0.1       39649
+INFO - -------
+INFO - Ready!
+INFO - Configuring enterprise application: /home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.example.jaxws.MeetingPlannerTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Creating Container(id=Default Managed Container)
+INFO - Using directory /tmp for stateful session passivation
+INFO - Enterprise application "/home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest" loaded.
+INFO - Creating dedicated application classloader for MeetingPlannerTest
+INFO - Assembling app: /home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest
+INFO - Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@49993335
+INFO - Some Principal APIs could not be loaded: org.eclipse.microprofile.jwt.JsonWebToken out of org.eclipse.microprofile.jwt.JsonWebToken not found
+INFO - OpenWebBeans Container is starting...
+INFO - Adding OpenWebBeansPlugin : [CdiPlugin]
+INFO - All injection points were validated successfully.
+INFO - OpenWebBeans Container has started, it took 406 ms.
+INFO - Webservice(wsdl=http://127.0.0.1:39649/demo/meeting-planner, qname={http://jaxws.example.superbiz.org/}MeetingPlannerImplService) --> Pojo(id=null./demo.jaxws)
+INFO - Deployed Application(path=/home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest)
+INFO - Creating Service {http://jaxws.example.superbiz.org/}MeetingPlannerImplService from WSDL: http://127.0.0.1:39649/demo/meeting-planner?wsdl
+INFO - Creating Service {http://jaxws.example.superbiz.org/}MeetingPlannerImplService from WSDL: http://127.0.0.1:39649/demo/meeting-planner?wsdl
+INFO - Undeploying app: /home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest
+INFO - Stopping network services
+INFO - Stopping server services
+INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@49993335
+INFO - Succeeded in installing singleton service
+INFO - Cannot find the configuration file [conf/openejb.xml].  Will attempt to create one for the beans deployed.
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Creating TransactionManager(id=Default Transaction Manager)
+INFO - Creating SecurityService(id=Default Security Service)
+INFO - Initializing network services
+INFO - Creating ServerService(id=cxf)
+INFO - Creating ServerService(id=httpejbd)
+INFO - Created ServicePool 'httpejbd' with (10) core threads, limited to (200) threads with a queue of (9)
+INFO - Initializing network services
+INFO -   ** Bound Services **
+INFO -   NAME                 IP              PORT
+INFO -   httpejbd             127.0.0.1       39649
+INFO - -------
+INFO - Ready!
+INFO - Configuring enterprise application: /home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.example.jaxws.MeetingPlannerTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Creating Container(id=Default Managed Container)
+INFO - Using directory /tmp for stateful session passivation
+INFO - Enterprise application "/home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest" loaded.
+INFO - Creating dedicated application classloader for MeetingPlannerTest
+INFO - Assembling app: /home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest
+INFO - Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@49993335
+INFO - Some Principal APIs could not be loaded: org.eclipse.microprofile.jwt.JsonWebToken out of org.eclipse.microprofile.jwt.JsonWebToken not found
+INFO - OpenWebBeans Container is starting...
+INFO - Adding OpenWebBeansPlugin : [CdiPlugin]
+INFO - All injection points were validated successfully.
+INFO - OpenWebBeans Container has started, it took 52 ms.
+INFO - Webservice(wsdl=http://127.0.0.1:39649/demo/meeting-planner, qname={http://jaxws.example.superbiz.org/}MeetingPlannerImplService) --> Pojo(id=null./demo.jaxws)
+INFO - Deployed Application(path=/home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest)
+INFO - Undeploying app: /home/bogdan/open_source/tomee-master/examples/applicationcomposer-jaxws-cdi/MeetingPlannerTest
+INFO - Stopping network services
+INFO - Stopping server services
+Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.076 sec
+
+Results :
+
+Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
+....
+
+Full example can be found https://github.com/apache/tomee/tree/master/examples/applicationcomposer-jaxws-cdi[here].
\ No newline at end of file
diff --git a/examples/applicationcomposer-jaxws-cdi/src/test/java/org/superbiz/example/jaxws/MeetingPlannerTest.java b/examples/applicationcomposer-jaxws-cdi/src/test/java/org/superbiz/example/jaxws/MeetingPlannerTest.java
index 8664015..6bbfa45 100644
--- a/examples/applicationcomposer-jaxws-cdi/src/test/java/org/superbiz/example/jaxws/MeetingPlannerTest.java
+++ b/examples/applicationcomposer-jaxws-cdi/src/test/java/org/superbiz/example/jaxws/MeetingPlannerTest.java
@@ -24,19 +24,26 @@ import org.apache.openejb.testing.EnableServices;
 import org.apache.openejb.testing.Module;
 import org.apache.openejb.testng.PropertiesBuilder;
 import org.apache.openejb.util.NetworkUtil;
-import org.codehaus.stax2.io.Stax2StringSource;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.util.JAXBSource;
 import javax.xml.namespace.QName;
+import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.ws.Dispatch;
 import javax.xml.ws.Service;
-import java.net.MalformedURLException;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
 import java.net.URL;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.Date;
 import java.util.Properties;
 
@@ -74,9 +81,34 @@ public class MeetingPlannerTest {
         final Service service = Service.create(
                 new URL("http://127.0.0.1:" + JAX_WS_PORT + "/demo/meeting-planner?wsdl"),
                 new QName("http://jaxws.example.superbiz.org/", "MeetingPlannerImplService"));
-        final JAXBContext jc = JAXBContext.newInstance(MeetingPlannerImpl.class);
-        final Dispatch<Object> dispatch = service.createDispatch(new QName("http://jaxws.example.superbiz.org/", "MeetingPlannerImplPort"), jc, Service.Mode.PAYLOAD);
+        final Dispatch<Source> dispatch = service.createDispatch(new QName("http://jaxws.example.superbiz.org/", "MeetingPlannerImplPort"), Source.class, Service.Mode.PAYLOAD);
 
-        //TODO - Complete
+        Date currentDate = new Date();
+        LocalDateTime nowPlusTwoDays = LocalDateTime.from(currentDate.toInstant().atZone(ZoneId.systemDefault())).plusDays(2);
+        String dateArgument = nowPlusTwoDays.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+
+        String request = "<ns1:book xmlns:ns1=\"http://jaxws.example.superbiz.org/\"><arg0>"+ dateArgument +"</arg0></ns1:book>";
+        Source invoke = dispatch.invoke(new StreamSource(new StringReader(request)));
+        String result = sourceToXMLString(invoke);
+
+        assertTrue(result.contains("<return>true</return>"));
+    }
+
+    private String sourceToXMLString(Source result) {
+        String xmlResult = null;
+        try {
+            TransformerFactory factory = TransformerFactory.newInstance();
+            Transformer transformer = factory.newTransformer();
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            OutputStream out = new ByteArrayOutputStream();
+            StreamResult streamResult = new StreamResult();
+            streamResult.setOutputStream(out);
+            transformer.transform(result, streamResult);
+            xmlResult = streamResult.getOutputStream().toString();
+        } catch (TransformerException e) {
+            e.printStackTrace();
+        }
+        return xmlResult;
     }
 }