4

I have a Spring MVC project. I wrote a code something like

@Controller
@RequestMapping("CallBack")
@WebService(name = "NotificationToCP", targetNamespace = "http://SubscriptionEngine.ibm.com")
public class CallbackController {

    @RequestMapping("")
    @ResponseBody
    @WebMethod(action = "notificationToCP")
    @RequestWrapper(localName = "notificationToCP", targetNamespace = "http://SubscriptionEngine.ibm.com", className = "in.co.mobiz.airtelVAS.model.NotificationToCP_Type")
    @ResponseWrapper(localName = "notificationToCPResponse", targetNamespace = "http://SubscriptionEngine.ibm.com", className = "in.co.mobiz.airtelVAS.model.NotificationToCPResponse")
    public NotificationToCPResponse index(
            @WebParam(name = "notificationRespDTO", targetNamespace = "") CPNotificationRespDTO notificationRespDTO) {
        return new NotificationToCPResponse();
    }
}

Can I use Spring MVC + Webservices together? What I want is just as a controller that accepts a SOAP request and process it. The url needs to be /CallBack. I'm still as a sort of confused being a Newbie. Will something like above work. Else how do I get it going.

Akhil K Nambiar
  • 3,835
  • 13
  • 47
  • 85
  • This will probably work. ("Probably" because I have never tried, but since those are just annotations, they can't have side-effects: whoever doesn't recognize them will just ignore them.) Just be aware that the instances that will handle the SOAP requests are not the same instances that will handle Spring MVC requests. – acdcjunior Jun 17 '13 at 02:16
  • Do you've any sample program? Can you share ? –  Apr 09 '15 at 11:22

2 Answers2

5

I wouldn't mix Spring MVC and SOAP webservice (JAX-WS) together since they serve different purpose.

Better practice is to encapsulate your business operation in a service class, and expose it using both MVC controller and JAX-WS. For example:

HelloService

@Service
public class HelloService {
    public String sayHello() {
        return "hello world";
    }
}

HelloController has HelloService reference injected via autowiring. This is standard Spring MVC controller that invoke the service and pass the result as a model to a view (eg: hello.jsp view)

@Controller
@RequestMapping("/hello")
public class HelloController {
    @Autowired private HelloService helloService;

    @RequestMapping(method = RequestMethod.GET)
    public String get(Model model) {
        model.addAttribute("message", helloService.sayHello());
        return "hello";
    }
}

A JAX-WS endpoint also invoke the same service. The difference is the service is exposed as a SOAP web service

@WebService(serviceName="HelloService")
public class HelloServiceEndpoint {
    @Autowired private HelloService helloService;

    @WebMethod
    public String sayHello() {
        return helloService.sayHello();
    }
}

Note that JAX-WS style web service above isn't guaranteed to automatically work on all Spring deployment, especially if deployed on non Java EE environment (tomcat). Additional setup might be required.

gerrytan
  • 40,313
  • 9
  • 84
  • 99
0

Yes, there are reasons why you may want to add a web service endpoint to an existing Spring MVC app. The problem is that you will likely need to have a different path for each, which is fine.

You will need two servlets, a standard dispatcher servlet for handling HTTP/MVC and a MessageDispatcherServlet for handling SOAP calls.

The config can be tricky. First understand that you will have a dependency mismatch with Spring MVC when you add in the Spring-ws dependencies. You will need to exclude Spring-web as follows in your pom:

<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
    <version>2.2.1.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Once you have taken care of that you will need to add in the two servlets, one to handle web requests through Spring MVC and one to handle SOAP.

I'm assuming no-xml config using Spring 4, SpringBoot is possible as well.

Here is the key code you will add to your web initializer:

DispatcherServlet servlet = new DispatcherServlet();

// no explicit configuration reference here: everything is configured in the root container for simplicity
servlet.setContextConfigLocation("");

/* TMT From Java EE 6 API Docs:
 * Registers the given servlet instance with this ServletContext under the given servletName.
 * The registered servlet may be further configured via the returned ServletRegistration object. 
 */

ServletRegistration.Dynamic appServlet = servletContext.addServlet("appServlet", servlet);
appServlet.setLoadOnStartup(1);
appServlet.setAsyncSupported(true);

Set<String> mappingConflicts = appServlet.addMapping("/web/*");

MessageDispatcherServlet mds = new MessageDispatcherServlet();
mds.setTransformWsdlLocations(true);
mds.setApplicationContext(context);
mds.setTransformWsdlLocations(true);

ServletRegistration.Dynamic mdsServlet = servletContext.addServlet("mdsServlet", mds);
mdsServlet.addMapping("/wsep/*");
mdsServlet.setLoadOnStartup(2);
mdsServlet.setAsyncSupported(true);

That is really all there is to it. The rest of the config is standard stuff, found in any number of examples.

For instance, you can mix the spring IO examples for Spring MVC and Spring-WS easily as a test bed. Just make sure you set up the WebMvcConfigurerAdapter and the WsConfigurerAdapter accordingly. They will be two separate classes, annotated individually with @Configuration @EnableWebMvc and @EnableWs @Configuration respectively. They will have to be added to the component scan complete with your @Endpoint classes.

Compile, run and test using a browser for the MVC stuff off the root context via /web/* and the SOAP calls using SoapUI by importing the WSDL and hitting /wsep/* off the root. Each path handled by each servlet.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
TechTrip
  • 4,299
  • 2
  • 21
  • 16