Goal of this exercise is to build a web service replacing a value in the request with an arbitrary value. This can be handy to fill e.g. SOAP header or HTTP header data to the message payload and make the data accessible in the service bean. Intended to use with declarative web services (OSGI blueprint / Spring configuration)
Prerequisites – knowledge of OSGi blueprint, CXF web services
Using Karaf 2.2.2-fuse-08-15, CXF 2.4.2
The main idea is to use interceptor to intercept incoming message and a value in the payload. For easy of use we will deserialize request objects and try to use POJO approach. This approach may have some overhead, but we consider it to be reasonable price to pay for easy usage.
Blueprint
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxws
http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://cxf.apache.org/blueprint/core
http://cxf.apache.org/schemas/blueprint/core.xsd
http://cxf.apache.org/blueprint/jaxws
http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://cxf.apache.org/blueprint/core
http://cxf.apache.org/schemas/blueprint/core.xsd
">
<bean
id="serviceBean"
class="com.apogado.test.interceptortest.InterceptorTestService" />
<bean
id="interceptor"
class="com.apogado.test.interceptortest.TestInterceptor" />
<jaxws:server id="InterceptorTestService"
address="/InterceptorTestService"
serviceClass="com.apogado.test.interceptortest.service.Test1Service"
serviceBean="#serviceBean">
<jaxws:inInterceptors>
<ref component-id="interceptor" />
</jaxws:inInterceptors>
</jaxws:server>
</blueprint>
Interceptor
package com.apogado.test.interceptortest;
import com.apogado.test.interceptortest.data.TDataRequest;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
/**
* a test interceptor to alter payload data
*
* @author Gabriel Vince
*/
public class TestInterceptor extends AbstractPhaseInterceptor {
private static final Logger logger = Logger.getLogger(TestInterceptor.class.getName());
public TestInterceptor() {
// the PRE_INVKE phase allows us access payload as objects and we don't
// need to worry some other object will mess it up
// security should be already checked
super(Phase.PRE_INVOKE);
}
/**
* get the request object and alter data there
* @param t
* @throws Fault
*/
public void handleMessage(Message t) throws Fault {
try
{
HttpServletRequest req = (HttpServletRequest)t.get("HTTP.REQUEST");
String queryString = req.getQueryString();
if (queryString != null
&& (queryString.contains("wsdl") || queryString.contains("WSDL"))
&& req.getMethod().equals("GET")) {
return; //let the schema request pass
}
logger.info("Test interceptor - processing data");
// Content formats available: org.w3c.dom.Node ,
// org.apache.cxf.io.DelegatingInputStream
// java.io.InputStream , java.util.List ,
// javax.xml.stream.XMLStreamReader
// seems only we reach payload as objects are using the List class
List list = t.getContent(List.class); // message parts
// TDataRequest is a request object generated from WSDL and XSD
// and used as a request message payload part
TDataRequest requestData = (TDataRequest) list.get(0);
requestData.setValue("An arbitrary value");
}
catch(Exception ex)
{
logger.log(Level.SEVERE, "test interceptor",ex);
}
}