Search code examples
web-servicestestingjax-wscxfopenejb

Test @Webservice EJBs with WebServiceContext (using OpenEJB?)


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


Solution

  • 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.

    The bean

    @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;
        }
    }
    

    The Test

    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));
        }
    }
    

    Libraries

    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.