Subscribed unsubscribe Subscribe Subscribe

igarashitm.log

igarashitm, a Japanese software engineer writes something in English here.

Connecting to HornetQ via remote JNDI provider

Today I have been trying to make my SwitchYard application connected to remote HornetQ, succeeded with following.

Add JNDI properties to the InitialContext

This piece is mentioned by Justin on this thread:
Accessing HornetQ using remote lookup via JNDI | Community

final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
env.put(Context.PROVIDER_URL, "remote://localhost:4447");
InitialContext ic = new InitialContext(env);
Add jboss-deployment-structure.xml into application.jar!/META-INF

This was the piece I've been looking for. org.jboss.naming.remote.client.InitialContextFactory is in the org.jboss.remote-naming module.

  • application.jar!/META-INF/jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="org.jboss.remote-naming" />
      <module name="org.hornetq" />
    </dependencies>
  </deployment>
</jboss-deployment-structure>


Once [SWITCHYARD-1712] JCA outbound cannot communicate with remote destinations/brokers - JBoss Issue Tracker is fixed, then SwitchYard JCA outbound should be able to connect to the HornetQ server via remote JNDI.

Message Ordering on HornetQ

An important tips - enable Message Group or limit "max-pool-size" to 1 to guarantee the order. Notice that the max-pool-size is only available on JBossAS7.2 or later.

How to order messages that are sent from the message queue? | SwitchYard | JBoss Community

Moving to Japan - Thanks to everybody I met in US

Finally, I need to accept the end of living in US. It has been the most amazing time in my life. I miss lots of beautiful historic structure in Boston city, and full of greenery once I just go 30 minutes away from the city.

In winter, not only I love to do snowboarding, but also I love the snowscape itself here. Snow plowing was also a kind of fun to me.

Summer, I regret that it was just only once to go to the Tanglewood Music Festival, and I couldn't go to Boston Symphony Hall at last.

People. I love people I met here in US. I remember somebody said to me that the service and staff in US is terrible, But I clearly disagree. I know the staff like waiter or operator is always polite in Japan, but they are just reading a manual, right? I love to be served by person, and I could in US. Yeah, there were a few impolite person, but I could just talk to other good person.

And Red Hat. I'm honored to have worked with them. They are highly motivated, professional and fun to talk - my poor English doesn't produce any joke, so I just have been listening though. I'll never dispose the "I miss you" mail from them so that I can see it when I'm captured into death march ;)

Bye for now, everybody and everything in US. Thank you so much so far. I'll see you again.


------------------------------------------------------------------------------


そしてUSで出会った日本人の皆さま、今までお世話になりました。同じ日本人とのほっこり一息というのは、異なる文化圏の人々と触れ合うのとはまた違う、これも欠かせないものだったと思います。またどこかでお会いできることを願っております。

JBoss AS7 remote debug

Standard installation

enable following option in $AS7/bin/standalone.conf

JAVA_OPTS="$JAVA_OPTS -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"


JUnit testcase kicked by Maven

mvn -Dmaven.surefire.debug test

or

mvn -Dmaven.surefire.debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000" test


Arquillian testcase

Add javaVmArguments property into arquillian.xml

...(snip)...
     <container qualifier="jboss7" default="true">
         <configuration>
+           <property name="javaVmArguments">-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</property> 
         </configuration>
...(snip)...

Playing around with SwitchYard on OpenShift Express

Install OpenShift Express Client Tools

yum install rubygem-rhc

Create an application with jbossas-7 cartridge

Used HelloSwitchYard as the application name.

rhc app create -l <openshift-account> -a HelloSwitchYard -t jbossas-7

Add SwitchYard Subsystem to the JBoss AS7

switchyard-openshift repository provides a way of that. Let's swipe it :)

cd HelloSwitchYard
git remote add switchyard-template git://github.com/jboss-switchyard/switchyard-openshift.git
git fetch switchyard-template
git checkout switchyard-template/master -- pom.xml
git checkout switchyard-template/master -- standalone.diff
git apply standalone.diff
git rm -f standalone.diff

Edit pom.xml

Fix the artifact name as you like and profile id in the OpenShift manner

diff --git a/pom.xml b/pom.xml
index 845c81c..44e8b12 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,11 +1,11 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
-  <groupId>org.switchyard.sample</groupId>
-  <artifactId>swydapp</artifactId>
+  <groupId>mynamespace.helloswitchyard</groupId>
+  <artifactId>HelloSwitchYard</artifactId>
 
   <version>1.0</version>
-  <name>swydapp</name>
+  <name>HelloSwitchYard</name>
   <properties>
     <switchyard.version>0.4.0.OS1</switchyard.version>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -43,9 +43,9 @@
   <build />
   <profiles>
     <profile>
-      <id>switchyard</id>
+      <id>openshift</id>
       <build>
-        <finalName>swydapp</finalName>
+        <finalName>HelloSwitchYard</finalName>
         <plugins>
           <plugin>
             <artifactId>maven-jar-plugin</artifactId>

Commit those changes

git add .
git commit -m "Added SwitchYard Subsystem"

Import the bean-service quickstart

Import the bean-service quickstart from SwitchYard distribution. bean-service is simple enough to use as template application

cp -r ${quickstarts}/bean-service/src/main/java/org src/main/java
cp -r ${quickstarts}/bean-service/src/main/resources/wsdl src/main/resources/
cp -r ${quickstarts}/bean-service/src/main/resources/META-INF src/main/resources/
cp -r ${quickstarts}/bean-service/src/test src/

Edit pom.xml

Edit pom.xml to add dependency on switchyard-component-bean, switchyard-component-soap, switchyard-test

diff --git a/pom.xml b/pom.xml
index 44e8b12..210a101 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,6 +21,18 @@
       <artifactId>switchyard-plugin</artifactId>
       <version>${switchyard.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.switchyard.components</groupId>
+      <artifactId>switchyard-component-bean</artifactId>
+      <version>${switchyard.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.switchyard.components</groupId>
+      <artifactId>switchyard-component-soap</artifactId>
+      <version>${switchyard.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.switchyard</groupId>
+      <artifactId>switchyard-test</artifactId>
+      <version>${switchyard.version}</version>
+    </dependency>
   </dependencies>
   <repositories>
     <repository>

Edit src/main/resources/META-INF/switchyard.xml

comment out the socketAddr & contextPath elements in the binding.soap element

diff --git a/src/main/resources/META-INF/switchyard.xml b/src/main/resources/META-INF/switchyard.xml
index 3d24bed..cb193bc 100644
--- a/src/main/resources/META-INF/switchyard.xml
+++ b/src/main/resources/META-INF/switchyard.xml
@@ -5,8 +5,8 @@
             <interface.wsdl interface="wsdl/OrderService.wsdl#wsdl.porttype(OrderService)"/>
             <binding.soap xmlns="urn:switchyard-component-soap:config:1.0">
                 <wsdl>wsdl/OrderService.wsdl</wsdl>
-                <socketAddr>:18001</socketAddr>
-                <contextPath>quickstart-bean</contextPath>
+                <!-- <socketAddr>:18001</socketAddr> -->
+                <!-- <contextPath>quickstart-bean</contextPath> -->
             </binding.soap>
         </service>
     </composite>

Edit src/test/java/org/switchyard/quickstarts/bean/service/WebServiceTest.java

Change the web service address in the testcase

diff --git a/src/test/java/org/switchyard/quickstarts/bean/service/WebServiceTest.java b/src/test/java/org/switchyard/quickstarts/bean/service/WebServiceTest.ja
index 4c6ac9e..ccdc7d0 100644
--- a/src/test/java/org/switchyard/quickstarts/bean/service/WebServiceTest.java
+++ b/src/test/java/org/switchyard/quickstarts/bean/service/WebServiceTest.java
@@ -41,7 +41,7 @@ public class WebServiceTest {
     public void invokeOrderWebService() throws Exception {
         // Use the HttpMixIn to invoke the SOAP binding endpoint with a SOAP input (from the test classpath)
         // and compare the SOAP response to a SOAP response resource (from the test classpath)...
-        httpMixIn.postResourceAndTestXML("http://localhost:18001/quickstart-bean/OrderService", "/xml/soap-request.xml", "/xml/soap-response.xml");
+        httpMixIn.postResourceAndTestXML("http://localhost:8080/OrderService", "/xml/soap-request.xml", "/xml/soap-response.xml");
     }
 }

Build and deploy

mvn -Popenshift clean package
git add .
git commit -m "Added bean-service"
git push

Check the status of application

rhc app status -l <openshift-account> -a HelloSwitchYard

Logs looks like this. Don't mind about some Japanese characters in my log, and an error as well. The important thing here is that HelloSwitchYard.jar has been Deployed successfully.

2012/03/14 14:55:38,258 INFO  [org.jboss.weld.deployer] (MSC service thread 1-2) JBAS016008: Starting weld service for deployment HelloSwitchYard.jar
2012/03/14 14:55:38,993 INFO  [org.switchyard] (MSC service thread 1-3) Starting SwitchYard service
2012/03/14 14:55:39,099 INFO  [org.apache.camel.impl.converter.AnnotationTypeConverterLoader] (MSC service thread 1-3) Found 3 packages with 14 @Converter classes to load
2012/03/14 14:55:39,109 INFO  [org.apache.camel.impl.converter.DefaultTypeConverter] (MSC service thread 1-3) Loaded 153 core type converters (total 153 type converters)
2012/03/14 14:55:39,111 INFO  [org.apache.camel.impl.converter.DefaultTypeConverter] (MSC service thread 1-3) Loaded additional 0 type converters (total 153 type converters) in 0.001 seconds
2012/03/14 14:55:40,197 INFO  [org.switchyard.component.soap.InboundHandler] (MSC service thread 1-3) Publishing WebService at http://127.13.2.129:18001/swydws/OrderService
2012/03/14 14:55:40,630 情報    [org.apache.cxf.service.factory.ReflectionServiceFactoryBean] (MSC service thread 1-3) Creating Service {urn:switchyard-quickstart:bean-service:1.0}OrderService from WSDL: vfs:/content/HelloSwitchYard.jar/wsdl/OrderService.wsdl
2012/03/14 14:55:41,376 情報    [org.apache.cxf.endpoint.ServerImpl] (MSC service thread 1-3) Setting the server's publish address to be http://127.13.2.129:18001/swydws/OrderService
2012/03/14 14:55:41,504 ERROR [org.jboss.as] (MSC service thread 1-3) JBAS015875: JBoss AS 7.1.0.Final "Thunder" started (with errors) in 7971ms - Started 143 of 178 services (1 services failed or missing dependencies, 31 services are passive or on-demand)
2012/03/14 14:55:41,549 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "HelloSwitchYard.jar"

Submit a WebService request using SoapUI

Assuming the namespace is "namespace", Import WSDL from http://helloswitchyard-namespace.rhcloud.com/swydws/OrderService?wsdl into SoapUI and invoke.

Request

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:switchyard-quickstart:bean-service:1.0">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:submitOrder>
         <order>
            <orderId>XYZ</orderId>
            <itemId>BUTTER</itemId>
            <quantity>200</quantity>
         </order>
      </urn:submitOrder>
   </soapenv:Body>
</soapenv:Envelope>

Response

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <orders:submitOrderResponse xmlns:orders="urn:switchyard-quickstart:bean-service:1.0">
         <orderAck>
            <orderId>XYZ</orderId>
            <accepted>true</accepted>
            <status>Order Accepted</status>
         </orderAck>
      </orders:submitOrderResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


Then you are all set to develop the SwitchYard application on OpenShift Express!
You may want to use the forge tool instead of editing switchyard.xml by hand. Let's see this:


Enjoy!

Debugging around JBossWS & apache-cxf without JBoss instance on Eclipse

Just a note for debugging SWITCHYARD-600.
Don't forget to mkdir ${project}/resources and add it to the build path.

Add system property when run/debug

-Djavax.xml.ws.spi.Provider=org.jboss.wsf.stack.cxf.client.ProviderImpl

resources/META-INF/cxf/bus-extensions.txt

org.apache.cxf.wsdl11.WSDLManagerImpl:org.apache.cxf.wsdl.WSDLManager:true
org.apache.cxf.phase.PhaseManagerImpl:org.apache.cxf.phase.PhaseManager:true
org.apache.cxf.workqueue.WorkQueueManagerImpl:org.apache.cxf.workqueue.WorkQueueManager:true
org.apache.cxf.buslifecycle.CXFBusLifeCycleManager:org.apache.cxf.buslifecycle.BusLifeCycleManager:true   	   
org.apache.cxf.endpoint.ServerRegistryImpl:org.apache.cxf.endpoint.ServerRegistry:true
org.apache.cxf.transport.http.QueryHandlerRegistryImpl:org.apache.cxf.transports.http.QueryHandlerRegistry:true 
org.apache.cxf.endpoint.EndpointResolverRegistryImpl:org.apache.cxf.endpoint.EndpointResolverRegistry:true
org.apache.cxf.headers.HeaderManagerImpl:org.apache.cxf.headers.HeaderManager:true
org.apache.cxf.catalog.OASISCatalogManager:org.apache.cxf.catalog.OASISCatalogManager:true
org.apache.cxf.service.factory.FactoryBeanListenerManager::true
org.apache.cxf.endpoint.ServerLifeCycleManagerImpl:org.apache.cxf.endpoint.ServerLifeCycleManager:true
org.apache.cxf.endpoint.ClientLifeCycleManagerImpl:org.apache.cxf.endpoint.ClientLifeCycleManager:true
org.apache.cxf.bus.resource.ResourceManagerImpl:org.apache.cxf.resource.ResourceManager:true

org.apache.cxf.binding.soap.SoapBindingFactory::true
org.apache.cxf.binding.soap.SoapTransportFactory::true

org.apache.cxf.transport.http.HTTPTransportFactory::true
org.apache.cxf.transport.http.HTTPWSDLExtensionLoader::true
org.apache.cxf.transport.http.policy.HTTPClientAssertionBuilder::true
org.apache.cxf.transport.http.policy.HTTPServerAssertionBuilder::true
org.apache.cxf.transport.http.policy.NoOpPolicyInterceptorProvider::true

org.jboss.wsf.stack.cxf.addons.transports.httpserver.HttpServerDestinationFactory::true

resources/wsdl.wsdl

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions 
    targetNamespace="urn:test" 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:tns="urn:test"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    
  <types>
    <xsd:schema 
        targetNamespace="urn:test" 
        xmlns:tns="urn:test" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="input" type="xs:string"/>
  </xsd:schema>
  </types>
  
  <message name="message">
    <part name="input" element="tns:input"/>
  </message>
  
  <portType name="service">
    <operation name="message">
      <input message="tns:message"/>
    </operation>
  </portType>
  
  <binding name="serviceBinding" type="tns:service">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <operation name="message">
      <soap:operation soapAction="urn:test"/>
      <input>
        <soap:body use="literal"/>
      </input>
    </operation>
  </binding>
  
  <service name="service">
    <port name="port" binding="tns:serviceBinding">
      <soap:address location="http://localhost:18080/test"/>
    </port>
  </service>
</definitions>

src/PublishWebService.java

Test code for javax.xml.ws.{Provider,Endpoint}. Using TCP socket to invoke the service.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Endpoint;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.WebServiceProvider;
import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;

@WebServiceProvider
@ServiceMode(Mode.MESSAGE)
public class PublishWebService implements Provider<SOAPMessage> {
    private static final String PUBLISH_URL = "http://127.0.0.1:18080/context/test";
    private static final String WSDL = "wsdl.wsdl";
    private static final String REQUEST_BODY =
            "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n" +
            "    <soap:Body>\r\n" +
            "        <test:input xmlns:test=\"urn:test\">foobar</test:input>\r\n" +
            "    </soap:Body>\r\n" +
            "</soap:Envelope>";

    @Override
    public SOAPMessage invoke(SOAPMessage request) {
        return null;
    }

    public void perform() throws Exception {
        Endpoint _endpoint = createEndpoint(WSDL);
        _endpoint.publish(PUBLISH_URL);
        
        Socket sock = new Socket("127.0.0.1", 18080);
        BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
        Thread t = new MyReader(reader);
        t.start();
        OutputStream out = sock.getOutputStream();
        String method = "POST /context/test HTTP/1.1\r\n";
        out.write(method.getBytes(), 0, method.getBytes().length);
        String contentLength = "Content-Length: " + REQUEST_BODY.length() + "\r\n";
        out.write(contentLength.getBytes(), 0, contentLength.getBytes().length);
        String contentType = "Content-Type: text/xml; charset=\"utf-8\"\r\n\r\n";
        out.write(contentType.getBytes(), 0, contentType.getBytes().length);
        
        out.write(REQUEST_BODY.getBytes(), 0, REQUEST_BODY.getBytes().length);
        String eof = "\r\n\r\n";
        out.write(eof.getBytes(), 0, eof.getBytes().length);
        out.flush();

        Thread.sleep(1000);
        sock.close();
        _endpoint.stop();
        System.out.println(">>>>> end.");
        System.exit(0);
    }
    
    private Endpoint createEndpoint(String wsdl) throws Exception {
        URL wsdlUrl = this.getClass().getResource(wsdl);
        javax.wsdl.Service wsdlService = getService(wsdlUrl);
        Port _wsdlPort = (Port) wsdlService.getPorts().values().iterator().next();

        List<Source> metadata = new ArrayList<Source>();
        StreamSource source = new StreamSource(this.getClass().getResourceAsStream(wsdl));
        source.setSystemId(wsdlUrl.toExternalForm());
        
        metadata.add(source);
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(Endpoint.WSDL_SERVICE, wsdlService.getQName());
        properties.put(Endpoint.WSDL_PORT, new QName(wsdlService.getQName().getNamespaceURI(), _wsdlPort.getName()));
        properties.put("javax.xml.ws.wsdl.description", wsdlUrl.toExternalForm());

        Endpoint _endpoint = Endpoint.create(this);
        _endpoint.setMetadata(metadata);
        _endpoint.setProperties(properties);
        return _endpoint;
    }
    
    private Service getService(URL wsdlUrl) throws Exception {
        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        docBuilderFactory.setNamespaceAware(true);
        DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();

        InputStream inputStream = wsdlUrl.openStream();
        InputSource source = new InputSource(inputStream);
        source.setSystemId(wsdlUrl.toString());
        Document wsdlDoc = builder.parse(source);
        WSDLFactory wsdlFactory = WSDLFactory.newInstance();
        WSDLReader reader = wsdlFactory.newWSDLReader();
        reader.setFeature("javax.wsdl.verbose", false);

        Definition definition = reader.readWSDL(wsdlUrl.toString(), wsdlDoc);
        Service service = null;
        service = (Service) definition.getServices().values().iterator().next();
        return service;
    }
    
    public static void main(String[] args) throws Exception {
        new PublishWebService().perform();
    }
}

class MyReader extends Thread {
    private BufferedReader reader;
    String line;
    
    public MyReader(BufferedReader reader) {
        this.reader = reader;
    }
    public void run() {
        while(true) {
            try {
                if ((line = reader.readLine()) != null) {
                    System.out.println(">>>>> received [" + line + "]");
                }
            } catch (IOException ignore) {break;}
        }
    }
}

resources/log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>

	<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d{HH:mm:ss,SSS} %-5p [%c] %m%n"/>
		</layout>
	</appender>

	<root>
		<level value="FINE"/>
		<appender-ref ref="STDOUT"/>
	</root>

</log4j:configuration>

XSLT transformation using DOMSource & DOMResult

Just reminder. really hit a wall.

The points are following two. It's no problem if the source is always String, but sometimes not somehow.

  1. need to do DocumentBuilderFactory#setNamespaceAware(true) when creating DOMSource from String, or XSLT transformation fails afterward. And what is worse, it doesn't return a error but empty result.
  2. DOMResult#getNode() actually returns Document, so need to do like this - ((Document)domresult.getNode()).getDocumentElement() - I don't like this. use getDocument() as method name if it returns the Document.

XsltTransformTest.java - Testcase using StreamSource, StreamResult as well

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;

public class XsltTransformTest {
    private static final String XML =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "<orders:order xmlns:orders=\"urn:switchyard-quickstart:transform-xslt:1.0\">\n" +
                    "    <orderId>PO-19838-XYZ</orderId>\n" +
                    "    <itemId>BUTTER</itemId>\n" +
                    "    <quantity>200</quantity>\n" +
                    "</orders:order>";
    
    private static final String XSLT =
            "<?xml version=\"1.0\"?>\n"
            + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
            + "    <xsl:template match=\"/\">\n"
            + "        <orders:orderAck xmlns:orders=\"urn:switchyard-quickstart:transform-xslt:1.0\">\n"
            + "            <xsl:for-each select=\"orders:order\">\n"
            + "                <orderId>\n"
            + "                    <xsl:value-of select=\"orderId\" />\n"
            + "                </orderId>\n"
            + "                <accepted>\n"
            + "                    <xsl:choose>\n"
            + "                        <xsl:when test=\"(itemId = 'BUTTER') and (quantity &lt;= 200)\">\n"
            + "                            true\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:otherwise>\n"
            + "                            false\n"
            + "                        </xsl:otherwise>\n"
            + "                    </xsl:choose>\n"
            + "                </accepted>\n"
            + "                <status>\n"
            + "                    <xsl:choose>\n"
            + "                        <xsl:when test=\"(itemId = 'BUTTER') and (quantity &lt;= 200)\">\n"
            + "                            Order Accepted\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:when test=\"itemId != 'BUTTER'\">\n"
            + "                            No Such Item:\n"
            + "                            <xsl:value-of select=\"itemId\" />\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:when test=\"quantity &gt; 200\">\n"
            + "                            Not Enough Stock\n"
            + "                        </xsl:when>\n"
            + "                        <xsl:otherwise>\n"
            + "                            UNKNOWN\n"
            + "                        </xsl:otherwise>\n"
            + "                    </xsl:choose>\n"
            + "                </status>\n"
            + "            </xsl:for-each>\n"
            + "        </orders:orderAck>\n"
            + "    </xsl:template>\n"
            + "</xsl:stylesheet>";
    
    public static void main(String[] args) throws Exception {
        new XsltTransformTest().perform();
    }
    
    public void perform() throws Exception {
        System.out.println("* * *  StreamSource => StreamResult  * * *");
        transform(XSLT, createStreamSource(XML), new StreamResult(System.out));
        System.out.println("\n* * *  DOMSource => StreamResult  * * *");
        transform(XSLT, createDOMSource(XML), new StreamResult(System.out));

        DOMResult result = new DOMResult();
        System.out.println("\n* * *  StreamSource => DOMResult  * * *");
        printDOMResult(transform(XSLT, createStreamSource(XML), result));
        result = new DOMResult();
        System.out.println("\n* * *  DOMSource => DOMResult  * * *");
        printDOMResult(transform(XSLT, createDOMSource(XML), result));
    }
    
    private void printDOMResult(DOMResult dom) throws Exception {
        System.out.println("getNode().getLocalName()="
                + dom.getNode().getLocalName()
                + ", ((Document)getNode()).getDocumentElement().getLocalName()="
                + ((Document)dom.getNode()).getDocumentElement().getLocalName());
    }

    private <T extends Result> T transform(String xslt, Source source, T result) throws Exception {
        javax.xml.transform.TransformerFactory tFactory = javax.xml.transform.TransformerFactory.newInstance();
        Templates templates = tFactory.newTemplates(new StreamSource(new StringReader(xslt)));
        javax.xml.transform.Transformer transformer = templates.newTransformer();
        transformer.transform(source, result);
        return result;
    }
    
    private DOMSource createDOMSource(String str) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        InputSource input = new InputSource(new StringReader(str));
        Document document = factory.newDocumentBuilder().parse(input);
        return new DOMSource(document.getDocumentElement());
    }
    
    private StreamSource createStreamSource(String str) throws Exception {
        return new StreamSource(new StringReader(str));
    }
}

output

* * *  StreamSource => StreamResult  * * *
<?xml version="1.0" encoding="UTF-8"?><orders:orderAck xmlns:orders="urn:switchyard-quickstart:transform-xslt:1.0"><orderId>PO-19838-XYZ</orderId><accepted>
                            true
                        </accepted><status>
                            Order Accepted
                        </status></orders:orderAck>
* * *  DOMSource => StreamResult  * * *
<?xml version="1.0" encoding="UTF-8"?><orders:orderAck xmlns:orders="urn:switchyard-quickstart:transform-xslt:1.0"><orderId>PO-19838-XYZ</orderId><accepted>
                            true
                        </accepted><status>
                            Order Accepted
                        </status></orders:orderAck>
* * *  StreamSource => DOMResult  * * *
getNode().getLocalName()=null, ((Document)getNode()).getDocumentElement().getLocalName()=orderAck

* * *  DOMSource => DOMResult  * * *
getNode().getLocalName()=null, ((Document)getNode()).getDocumentElement().getLocalName()=orderAck