1

I am creating Restful (Jax-RS) services to be deployed to Fuse 6.2.1. (using Apache CFX, and deploying with OSGi bundles to Karaf) The server supports only up to Spring 3.2.12.RELEASE. I am attempting to do everything with next to zero XML configuration.

So far so good, everything is working and I can deploy and run my services.

However, I'd like to be able to test my services locally without having to deploy them. So I'd like to be able to boostrap a webserver and register my servlet, but can't quite figure our how.

I'm configuring the servlet with this (using Spring's WebApplicationInitializer rather than web.xml):

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

public class CxfServletInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    servletContext.addListener(new ContextLoaderListener(createWebAppContext()));
    addApacheCxfServlet(servletContext);
}

private void addApacheCxfServlet(ServletContext servletContext) {
    CXFServlet cxfServlet = new CXFServlet();
    ServletRegistration.Dynamic appServlet = servletContext.addServlet("CXFServlet", cxfServlet);
    appServlet.setLoadOnStartup(1);
    Set<String> mappingConflicts = appServlet.addMapping("/*");
}

private WebApplicationContext createWebAppContext() {
    AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
    appContext.register(CxfServletConfig.class);
    return appContext;
}

}

And my main Spring config looks like this:

import javax.ws.rs.core.Application;
import javax.ws.rs.ext.RuntimeDelegate;

import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;

@Configuration
public class CxfServletConfig {

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CxfServletConfig.class);

@Bean(destroyMethod = "shutdown")
public SpringBus cxf() {
    return new SpringBus();
}

@Bean
@DependsOn("cxf")
public Server jaxRsServer(ApplicationContext appContext) {
    JAXRSServerFactoryBean endpoint = RuntimeDelegate.getInstance(). 
        createEndpoint(jaxRsApiApplication(), JAXRSServerFactoryBean.class);

    endpoint.setServiceBeans(Arrays.<Object> asList(testSvc()));
    endpoint.setAddress(endpoint.getAddress());
    endpoint.setProvider(jsonProvider());
    return endpoint.create();
}

@Bean
public Application jaxRsApiApplication() {
    return new Application();
}

@Bean
public JacksonJsonProvider jsonProvider() {
    return new JacksonJsonProvider();
}

@Bean(name = "testSvc")
public TestService testSvc() {
    return new TestService();
}

So just to be clear, the above code is my current, working, deployable configuration. So now I'd like to create a test config that utilizes the same but which also starts Jetty and registers my servlet, and can't quite figure out how. Any help? Thanks!


EDIT: Turns out I did not need the WebApplicationInitializer at all to get this to work. I ended up creating a Test config for Spring that defines a Jetty server as a bean. Seems to work:

@Configuration
public class TestingSpringConfig {

@Bean (name="jettyServer", destroyMethod = "stop")
public Server jettyServer() throws Exception {

    Server server = new Server(0); //start jetty on a random, free port
    // Register and map the dispatcher servlet
    final ServletHolder servletHolder = new ServletHolder( new CXFServlet() );
    final ServletContextHandler context = new ServletContextHandler();  
    context.setContextPath( "/" );
    //fuse uses cxf as base url path for cxf services, so doing so as well here so urls are consistent
    context.addServlet( servletHolder, "/mybaseurl/*" );
    context.addEventListener( new ContextLoaderListener() );

    context.setInitParameter( "contextClass", AnnotationConfigWebApplicationContext.class.getName() );
    //this will load the spring config for the CFX servlet
    context.setInitParameter( "contextConfigLocation", CxfServletConfig.class.getName() );

    server.setHandler( context );
    server.start();
    //server.join(); if running from a main class instead of bean
    return server;
}

@Bean(name = "jettyPort")
@DependsOn("jettyServer")
public Integer jettyPort() throws Exception {
    Integer port = jettyServer().getConnectors()[0].getLocalPort();
    log.info("Jetty started on port: " + port);
    return  port;
}
}
crig
  • 859
  • 6
  • 19

0 Answers0