I have some EJBs as JAX-WS Web Service:
@WebService
@Stateless
@Remote(MobileFacade.class)
public class MobileFacadeBean implements MobileFacade {
...
@Resource
WebServiceContext wsc;
...
}
Within this Web Service class, a WebServiceContext is injected via @Resource. I use this WebServiceContext to get the principal in the implementation. This works quite well, but now I wonder how to (Unit-)test this class!
So far, I was using OpenEJB to test my EJBs. Since the Web Service class also is an Stateless Session Bean, I would really like to use the same approach here. However, it does not work that easy - of course, it complains that there is no WebServiceContext when not called as a Web Service.
So the first question is: are there any ways to mock the WebServiceContext in OpenEJB?
And if no, what approach would you favour to test this kind of Web Service classes?
Cheers, Frank
There are a handful of @WebService
unit test examples in the OpenEJB examples zip file. Everything you want should work fine.
The webservice-security example sounds exactly like what you want. The version online uses @RolesAllowed
to make the container do the security check rather than doing it in code, but it is possible to check the principle in code. Here's a slightly modified version of that example that worked for me with no issues.
@DeclareRoles(value = {"Administrator"})
@Stateless
@WebService(
portName = "CalculatorPort",
serviceName = "CalculatorWsService",
targetNamespace = "http://superbiz.org/wsdl",
endpointInterface = "org.superbiz.calculator.CalculatorWs")
public class CalculatorImpl implements CalculatorWs, CalculatorRemote {
@Resource
private WebServiceContext webServiceContext;
@RolesAllowed(value = {"Administrator"})
public int sum(int add1, int add2) {
// maybe log the principal or something -- prints "jane" in the test
System.out.print(webServiceContext.getUserPrincipal());
return add1 + add2;
}
@RolesAllowed(value = {"Administrator"})
public int multiply(int mul1, int mul2) {
return mul1 * mul2;
}
}
public class CalculatorTest extends TestCase {
private InitialContext initialContext;
protected void setUp() throws Exception {
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
properties.setProperty("openejb.embedded.remotable", "true");
initialContext = new InitialContext(properties);
}
/**
* Create a webservice client using wsdl url
*
* @throws Exception
*/
public void testCalculatorViaWsInterface() throws Exception {
URL url = new URL("http://127.0.0.1:4204/CalculatorImpl?wsdl");
QName calcServiceQName = new QName("http://superbiz.org/wsdl", "CalculatorWsService");
Service calcService = Service.create(url, calcServiceQName);
assertNotNull(calcService);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
((BindingProvider) calc).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "jane");
((BindingProvider) calc).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "waterfall");
assertEquals(10, calc.sum(4, 6));
assertEquals(12, calc.multiply(3, 4));
}
}
If using maven, switch your normal openejb-core
dependency to openejb-cxf
like so. This will add Apache CXF and the OpenEJB/CXF integration code to your classpath.
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-cxf</artifactId>
<version>3.1.4</version>
<scope>test</scope>
</dependency>
If not using maven, simplest approach is to just add all the jars from the lib/
directory of the OpenEJB zip file.