First, we create a class Webservice for contribution web services to a RequestFilter:
package org.apache.tapestry.webservice;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.xml.ws.handler.Handler;
public class Webservice
{
private final Class webserviceClass;
private final Object service;
private final String name;
private final String urlPattern;
@SuppressWarnings("rawtypes")
private final List handlerChain;
@SuppressWarnings("rawtypes")
public Webservice(Class webserviceClass, Object service, String name, String urlPattern, Handler... handlerChain)
{
super();
this.webserviceClass = webserviceClass;
this.service = service;
this.name = name;
this.urlPattern = urlPattern;
if(handlerChain == null)
this.handlerChain = Collections.emptyList();
else
this.handlerChain = Arrays.asList(handlerChain);
}
public Class getWebserviceClass()
{
return webserviceClass;
}
public Object getService()
{
return service;
}
public String getName()
{
return name;
}
public String getUrlPattern()
{
return urlPattern;
}
@SuppressWarnings("rawtypes")
public List getHandlerChain()
{
return handlerChain;
}
}
Next, we create a HttpServletRequestFilter for handling web service requests and forwarding them tho Metro / JAX-WS:
package org.apache.tapestry.webservice;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.handler.Handler;
import org.apache.tapestry5.services.ApplicationGlobals;
import org.apache.tapestry5.services.HttpServletRequestFilter;
import org.apache.tapestry5.services.HttpServletRequestHandler;
import com.sun.xml.ws.api.BindingID;
import com.sun.xml.ws.api.WSBinding;
import com.sun.xml.ws.api.server.Container;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.ws.binding.BindingImpl;
import com.sun.xml.ws.server.EndpointFactory;
import com.sun.xml.ws.transport.http.DeploymentDescriptorParser.AdapterFactory;
import com.sun.xml.ws.transport.http.servlet.ServletAdapter;
import com.sun.xml.ws.transport.http.servlet.ServletAdapterList;
import com.sun.xml.ws.transport.http.servlet.WSServletDelegate;
public class JaxWsHttpServletRequestFilter implements HttpServletRequestFilter
{
private final ServletContext servletContext;
private final WSServletDelegate wsServletDelegate;
private final List urlPatterns;
public JaxWsHttpServletRequestFilter(final List webservices,
final ApplicationGlobals applicationGlobals) throws MalformedURLException
{
this.servletContext = applicationGlobals.getServletContext();
Container servletContainer = new ServletContainer(servletContext);
AdapterFactory adapterFactory = new ServletAdapterList();
urlPatterns = new ArrayList();
List adapters = new ArrayList();
for (Webservice webservice : webservices)
{
WSBinding binding = BindingImpl.create(BindingID.parse(webservice.getWebserviceClass()));
@SuppressWarnings("rawtypes")
List handlerChain = binding.getHandlerChain();
handlerChain.addAll(webservice.getHandlerChain());
binding.setHandlerChain(handlerChain);
@SuppressWarnings("rawtypes")
WSEndpoint endpoint = EndpointFactory.createEndpoint(
webservice.getWebserviceClass(),
false,
new ServiceInvoker(webservice.getService()),
null,
null,
servletContainer,
binding,
null,
null,
null,
true);
adapters.add(adapterFactory.createAdapter(webservice.getName(), webservice.getUrlPattern(), endpoint));
urlPatterns.add(webservice.getUrlPattern());
}
wsServletDelegate = new WSServletDelegate(adapters, servletContext);
}
public boolean service(HttpServletRequest request, HttpServletResponse response, HttpServletRequestHandler handler)
throws IOException
{
String path = request.getServletPath();
String pathInfo = request.getPathInfo();
if (pathInfo != null)
path += pathInfo;
for (String urlPattern : urlPatterns)
{
if (path.startsWith(urlPattern))
{
try
{
wsServletDelegate.doPost(request, response, servletContext);
return true;
}
catch (ServletException e)
{
return false;
}
}
}
// Not a match, so let it go.
return handler.service(request, response);
}
}
In the WebServiceModule we add the JaxWsHttpServletRequestFilter:
public final class WebserviceModule
{
public static void contributeHttpServletRequestHandler(
OrderedConfiguration configuration,
@InjectService("JaxWsHttpServletRequestFilter") HttpServletRequestFilter jaxWsHttpServletRequestFilter)
{
configuration.addInstance("jaxws", JaxWsHttpServletRequestFilter.class, "after:*");
}
}
Now you can add your web service contribution to your module:
public static void contributeJaxWsHttpServletRequestFilter(final OrderedConfiguration configuration, final MyWebservice myWebservice)
{
configuration.add("MyWebservice", new Webservice(MyWebservice.class, myWebservice,
"MyWebservice", "/ws/MyWebservice", new SOAPLoggingHandler(
GWS_IMPORT_ORDER_LOGGER_NAME)));
}