Convert Spring MVC project to JAX-RS - spring

I'm trying to do a project with JAX-RS, Spring, Hibernate, Maven and JPA. I'm following this article as reference. This project is in Spring MVC. I'm very new to Spring MVC. I have tried to convert it to JAX-RS. What are the important changes I have to do with this?
The main change I noticed that in Spring MVC we use like this: #RequestMapping("/accounts/{username}").
But in JAX-RS we use like this. #Path("/accounts/{username}")
Therefore If I do the changes like this, what are the other key changes we have to do with this?

The most basic thing you need to do in order to port the Spring MVC controllers to JAX-RS controllers, is to provide and integration between Spring and your JAX-RS provider. One way to do that is to make the appropriate changes to web.xml.
Assuming you are using Jersey 2.x and Spring 3.x, the web.xml would look like:
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<module-name>helloworld-spring</module-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>SpringApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>some.package.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringApplication</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Then MyApplication would look like:
package some.package;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
public class MyApplication extends ResourceConfig {
public MyApplication () {
register(RequestContextFilter.class);
register(JerseyResource.class);
register(SpringSingletonResource.class);
register(SpringRequestResource.class);
register(CustomExceptionMapper.class);
}
}
You will also need the dependency
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>2.10.1</version>
</dependency>
besides the other Spring 3 and Jersey 2 dependencies.
Once you get that out of the way, you can start transforming the controllers.
For example:
#Path("admin")
#Component
public class AdminController {
#Autowired
private SchoolService service;
#Path("load-home-page")
#GET
public String loadHomePage(Map model){
return "admin/index";
}
//the rest of the code accordingly
}
The documentation for Spring-Jersey integration is here while a complete example can be found here.
Personally I would go the Spring MVC route instead of Jersey if you really don't have a compelling reason to choose Jersey over Spring MVC.

Related

Creating a route with Spring in Netbeans

I know this is a pretty basic issue, but I struggle hard with it...
I'd like to create a bunch of routes with the Spring framework in the Netbeans IDE, I have created a test #Controller class:
#Controller
public class HelloController {
#RequestMapping("/test")
public ModelAndView thisIsATest(HttpServletRequest request) {
return (new ModelAndView("myTestPage.jsp"));
}
}
myTestPage.jsp is a JSP file in the WEB-INF/jsp/ folder, and the HelloController class is in the Source Packages/ folder within a controller java package.
When I start the server, I can acces the root '/index.htm' that displays the index.jsp page (from the redirect.jsp file), but when I try to access '/test' or '/test.htm' I get a 404 error...
I really don't know how to make a Spring controller to work, and I did many tutorials without success.
In your applications web.xml make sure you have something like this. This will allow access to all your jsp pages. Add any other filters you may need here too.
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>myapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
</web-app>

Spring Data REST with Spring MVC: Adding RepositoryRestMvcConfiguration to existing DispatcherServlet

I have an existing Spring MVC Application with a DispatcherServlet and an XML based configuration.
Now I would like to integrate Spring Data REST but I dont know how to do this in a clean way. I added
<context:component-scan>...</context:component-scan>
so my RestControllers are found but I fail in adding a RepositoryRestMvcConfiguration config. I tried the annotation driven approach which doesnt work
#Configuration
public class RestConfiguration extends RepositoryRestMvcConfiguration {
...
}
and the
<bean class="com.mypackage.rest.RestConfiguration" />
approach is not working either.
I also tried the follwing in the web.xml
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.mypackage.rest.RestConfiguration</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Strange thing is, a method annotated with #PostConstruct is called, but non of the configure* methods.
In the docs for Spring Data REST is a chapter where it is explained how to add a Spring Data REST to a Spring MVC application in code. It also says
The equivalent of the above in a standard web.xml will also work identically to this configuration if you are still in a servlet 2.5 environment.
How do you do this?
Fortunately, in Section 11.2 it is explained. Would have been nice to have a reference in Section 2.5 that points to Section 11.2 :-/
In Java, this would look like:
import org.springframework.context.annotation.Import;
import org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration;
#Configuration
#Import(RepositoryRestMvConfiguration.class)
public class MyApplicationConfiguration {
…
}
In XML this would look like:
<bean class="org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration"/>

WSServletContainerInitializer and SpringBeanAutowiringSupport

I have some integration issues regarding the mentioned classes but only with "too new" tomcat versions.
The base setup:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="FooService" version="2.5" metadata-complete="true">
<display-name>FooService</display-name>
<servlet>
<servlet-name>jax-ws</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
</web-app>
FooServiceImpl:
#WebService(serviceName = ServiceInfo.SERVICENAME, targetNamespace = ServiceInfo.TARGETNAMESPACE, endpointInterface = "bar.FooService")
#HandlerChain(file = "/handler-chain.xml")
public class FooServiceImpl extends SpringBeanAutowiringSupport implements FooService {
#Autowired
private Bar bar;
<< some methods using the injected bar singleton >>
JAX-WS dependency: compile 'com.sun.xml.ws:jaxws-rt:2.2.7'
Spring version: 3.1.2.RELEASE
With Tomcat 7.0.22 I don't have the problem. The declared webapp version in the web.xml is 2.5. Tomcat 7.0.22 doesn't process the WSServletContainerInitializer. So as declared in web.xml, ContextLoaderListener is initialized first, so an instance of Bar will be available in the WebApplicationContext. Then WSServletContextListener instantiates FooServiceImpl, aoutowiring works and everybody is happy.
But... My colleague tried it with Tomcat 7.0.30 and the autowiring didn't work (7.0.32 gives the same problem, currently this is the newest). It really couldn't work, because the new Tomcat version has processed WSServletContainerInitializer, not taking into account the 2.5 webapp version (and metadata-complete="true").
I've found a possible solution. I commented out the body of the web.xml, changed webapp version to 3.0 and created a WebapplicationInitializer:
public class MyInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
ContextLoader loader = new ContextLoader();
loader.initWebApplicationContext(servletContext);
}
}
This worked perfectly for me. But not for my colleague... If he tried to run the app, WSServletContainerInitializer fired first which created exactly the same wiring problem as above.
Obviously we can "hack" the problem getting rid of SpringBeanAutowiringSupport and inject Bar manually from a getter or a web method, or any similar way. But SpringBeanAutowiringSupport would be much clearer, so we would like to use it if there's a good solution for the above problems.
UPDATE: this causes the problems: https://issues.apache.org/bugzilla/show_bug.cgi?id=53619
for me the solution was to invoke the following when the autowired reference is null
processInjectionBasedOnCurrentContext(this);
I hope it helps for all.

Spring MVC but without a view resolver?

is it possible to use Spring 3.1 MVC without using a view resolver?
The reason why i ask is because i simply want to build and create a Web service, not a Website so i do not need to render any JSP or html pages at all. I want to build a RESTful Web service using Spring 3.1.
Is this possible?
this is how my servlett looks like which is taken from a tutorial:
Here is my mvc-config.xml
Here is my Web.xml
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>FreedomSpring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FreedomSpring</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.xml</param-value>
</context-param>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
And here is my controller java class that simply want to return a String from a specific http REST request and not a "ModelAndView" object so to speak
package com.jr.freedom.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class Hello {
#RequestMapping(value = "/hello", method = RequestMethod.GET)
public String helloWorldInJson() {
return "hello";
}
}
Also, How can i capture a requests Parameters that a client may send me? is that possible using springs annototations? i know that i can in previous Spring 2.x use HttpServletRequest and HttpServletResponse to get any parameters sent from a client and also return a object back to the user as well such as a JSON object.
i am just looking for a simple example that does this:
Get parameters and possibly HTTP headers from a clients Request on my controller class and map them to some Java object "example, a client sends me details of a new user object registering to my backend service(username, password etc etc) and i want to be able to map this to my Java class Called User"
Return a response of any kind of object such as a String, json or xml data to a client.
Im quite new to Spring 3.0. i did a bit of work on Spring 2.0 long ago but annotations seems the way to go now and do not know how to do it via annotations.
Thanks
Also, To execute the above controller method of helloWorldInJson() do i simply call http://localhost/FreedomSpring/hello ?
You generally use #ResponseBody for this.
See 16.3.3.5 Mapping the response body with the #ResponseBody annotation.
This bypasses the view resolver stuff altogether.
use #RestController instead of #Controller.
This page shows what you want to achieve.
You would use the #PathVariable annotation to inject parameters encoded in the url as method parameter. If the parameters are in the post or the get, then you would use #RequestParam instead.
This doc also explain how to use a view resolver to marshall your model (set by your controller) into any format.
Yes, you can do. I just created spring mvc showcase project. you can find source code here.
https://github.com/mohansaravanan/spring/tree/master/springmvc-3.2.2
You may like this project!

Spring 3, Flex 4 Integration with SpringFlex 1.5.0.M2 api + configuration

We are working on a project where we are using Spring 3 to create a web platform and using Flex 4 to create a specific client side application. Currently, we need to integrate Spring project with Flex.
We are using Spring-Flex integration library version: 1.5.0.M2
I checked the older questions but the integration configurations defined at those entries are generally for previous versions of BlazeDS and Spring. And as I understad, there may be some differencies.
Can anybody tell me how to do the configuration in web.xml and any other xml files needed,and how the folder structures will be. Any up-to-date tutorial links will be appreciated.
Our business requirements are:
Two servlets should exist: 1) projectServlet that has mappings /.html
2) flexServlet that has mappings /messageBroker/
Our service classes that can be used in Flex side will be like:
package com.ecognitio.service;
import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.flex.remoting.RemotingInclude;
import org.springframework.stereotype.Service;
#Service
#RemotingDestination
public class Foo {
#RemotingInclude
public void sayHello(String name){
System.out.println("Hello: "+name);
}
}
Regards,
Ugur
My Flex 4, Hibernate 3, and Spring 3 Integration Refcard walks through the process of setting everything up and should work fine with 1.5.0.M2 (assuming you have changed the namespace in the Spring config file). But here is a basic web.xml example:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns
/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Project Template</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</liste
ner-class>
</listener>
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>
<servlet>
<servlet-name>flex</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>flex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
</web-app>
That should be enough to get you started.

Resources