Spring API Produce JSON or XML - spring

I need to create an API that can produce either XML or JSON.
So for example if the path requested is
/getData?format=XML
it should produce XML and if the path requested is
/getData?format=JSON
is should produce JSON.
I've gone through the Spring tutorial "Build a RESTful web service"
So I simply want to take that code and alter it so it will produce XML as well as JSON.
What are the steps I should take?

Step 1: Make sure you have Jackson 2 and Castor on the classpath for JSON and XML rendering respectively. If using Maven, these can be added as dependencies. You can also use GSON for JSON and JAXB for XML.
Step 2: Return a Java object from the controller method, something like:
#RequestMapping("/users")
public #ResponseBody Users all()
{
return ServiceLocator.findUserService().all();
}
Step 3: Configure the JSON and XML converters in the Spring application context file as follows:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="prettyPrint" value="true" />
<property name="supportedMediaTypes" value="application/json" />
</bean>
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg>
<bean class="org.springframework.oxm.castor.CastorMarshaller" />
</constructor-arg>
<property name="supportedMediaTypes" value="application/xml" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Step 4: Configure a ContentNegotiatingViewResolver in the Spring application context file as follows:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
</bean>
Once these steps have been completed, different representations can be obtained in multiple ways:
XML
http://server/users.xml
http://server/users?format=xml
http://server/users with the HTTP header Accepts set to application/xml
JSON
http://server/users.json
http://server/users?format=json
http://server/users with the HTTP header Accepts set to application/json

Related

`mvc:message-converters` ignored in Spring 5

We used to have the following configuration to customize our message converters in Spring 4:
<mvc:annotation-driven conversion-service="conversionService" content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="myObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
But after migrating to Spring 5, the above configuration has lost any effect (the default message converters take place).
If I define the bean explicitly, it works:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="objectMapper" ref="myObjectMapper" />
</bean>
</property>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttannotation-drivenpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
</list>
</property>
</bean>
Any idea why the mvc:message-converters tag stopped working?
ps. While debugging the issue I also noticed several instances of RequestMappingHandlerAdapter being instantiated in all cases, even though I would expect them to be a singleton. The latter significantly obscures debugging, since I'm not sure which is the right one to attribute message converters to to investigate.
pps. Another report of this issue:
https://stackoverflow.com/a/49156186/657723
In this case mvc:message-converters was overridden by another, empty mvc:annotation-driven which happened to be unnoticeably included down the chain of child xml inclusions.
In any case, the major problem was the silent override, which should have better be an error.

Put a spring bean into the Application scope?

This is related this question:
I need to inject a Spring bean into the Tomcat application's scope at startup:
<beans:bean id="myUrl" class="java.lang.String" >
<beans:constructor-arg type="java.lang.String">
<beans:value>${my.registry.location:some.url}</beans:value>
</beans:constructor-arg>
</beans:bean>
Is there a slick way to do this from the Spring XML configuration or do I need to override some servlet method (ugh)?
I thought I would post this in case it helps someone. Spring has a bean that will do this on initialization for you: ServletContextAttributeExporter.
You use it like this:
<bean id="myBean" class="java.lang.String" >
<constructor-arg type="java.lang.String">
<value>${some.property.value}</value>
</constructor-arg>
</bean>
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="myBean" value-ref="myBean" />
</map>
</property>
</bean>
You can then do something like this in your non-Spring aware JSP code (for example):
<div>
Value of my bean is: ${applicationScope.myBean}
</div>

What is the purpose of conversion-service and content-negotiation-manager in Spring?

What is the purpose of conversion-service and content-negotiation-manager in Spring? We have this in our Spring appContext but I am not sure about its purpose.
For content-negotiation-manager:
I have read here:
http://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-config-content-negotiation that the content-negotiation-manager acts like a 'resolver' for #RequestMapping - e.g. if my mapping URL is "/person/create" - it will be called when the client accesses /person/create.json and /person/create.html (given the configuration below).
I am also able to access /person/list.xml and it returns an xml result even if xml is not defined in the content-negotiation-manager since I have the Jackson in my classpath:
For file extensions in the request URI, the MVC Java config and the
MVC namespace, automatically register extensions such as .json, .xml,
.rss, and .atom if the corresponding dependencies such as Jackson,
JAXB2, or Rome are present on the classpath.
So, we defined the content-negotiation-manager since we support html, and it is not mapped by default. Is my understanding correct?
For conversion-service:
In our classes, we have an ObjectMapper.readValue(json, Obj.class) and #RestController returning an object in xml/json format depending on the request (it returns an xml format if you access /list.xml and returns json format when you access /list.json). But I've read that #RestController can work without the conversion-service. So I am not sure why it is supplied in the <mvc:annotation-driven>
<mvc:annotation-driven conversion-service="conversionService" content-negotiation-manager="contentNegotiationManager"/>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="html" value="text/html"/>
</map>
</property>
<property name="defaultContentType" value="application/json"/>
</bean>
Both the conversion service and the content negotation manager are always used by Spring MVC, regardless whether you define them or not. You can configure them according to your needs. That's the case here.
E.g. name="defaultContentType" value="application/json" means that if the client doesn't prefer a specific media type the server should send back JSON.

Spring Vs Struts + Freemarker

For a Web application If I've choices between Spring and Struts to use with Freemarker, which one go well, Or I would rather ask, which MVC framework integrates smoothly with Freemarker?
The Spring framework provides everything you need to use FreeMarker for your view layer.
Both have pretty good freemarker support. Its easy to turn on.
Struts2 is a little more pojo based. Spring is a little closer to the servlet api. Spring's default macros in spring.ftl need a little work and you will likely need to roll your own. Some of the macros blow up if an object is not present rather than gracefully testing for it and moving on if it is not there.
I like Spring's application of validation via annotations better than Struts 2 default validation. However, persisting validation errors over redirects is easier in Struts2. For Spring you'll end up needing to roll your own solution where I feel the framework should hide more of that. Needing to use the error prone spring.bind macro with freemarker templates is more cumbersome than it needs to be.
Spring 3.1 is supposed to provide better support for this validation errors living over redirects.
Also note, with Spring I typically use more than one view resolver. e.g. I still leaving support for .jsp on.
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"/>
<entry key="ftl" value="text/html"/>
<entry key="xml" value="application/xml"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="favorPathExtension" value="true"/>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
</list>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="order" value="1"/>
<property name="prefix" value="/"/>
<property name="suffix" value=".ftl"/>
<property name="contentType" value="text/html;charset=UTF-8"/>
<property name="exposeSpringMacroHelpers" value="true"/>
<property name="requestContextAttribute" value="rc"/>
<property name="exposeSessionAttributes" value="true"/>
<property name="exposeRequestAttributes" value="true"/>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
</bean>

Spring MVC from 2.5 to 3.0

We are migrating our web application from Spring 2.5 to Spring 3.0.5. Looks like all the Controller classes (the classes in org.springframework.web.servlet.mvc package: BaseCommandController, AbstractCommandController, SimpleFormController, etc) have been deprecated. We used those classes heavily in our application. These classes have been replaced by #Controller annotation instead.
I have a few questions regarding Spring 3.0.x Controller configuration...
We used the following XML to create a Controller bean in Spring 2.5. If <context:component-scan> is used instead to create the Controller beans, then how do I wire-in the dependencies? If possible I would like to avoid Auto-Wiring.
<bean id="photosetViewController" class="com.xyz.web.PhotosetViewController"
p:photosetManager-ref="photosetManager"
p:photoManager-ref="photoManager" />
We have created 3 Interceptors. We use SimpleUrlHandlerMapping to map these Interceptors to different request URLs and also to map URLs to Controllers. How do we achieve the same in Spring 3.0.x?
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true" />
<property name="interceptors">
<list>
<ref bean="httpRedirectInterceptor"/>
<ref bean="loginInterceptor"/>
</list>
</property>
<property name="mappings">
<value>
/abc.html=abcLookupController
/photoupload.html=photoUploadController
</value>
</property>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true" />
<property name="interceptors">
<list>
<ref bean="httpRedirectInterceptor"/>
<ref bean="loginInterceptor"/>
<ref bean="userMenuInterceptor" />
</list>
</property>
<property name="mappings">
<value>
/index.html=homepageController
/success.html=simpleController
</value>
</property>
</bean>
In case of SimpleFormControllers we used different methods like initBinder, referenceData, formBackingObject. We also used command objects and validation classes. How do we achieve the same in Spring 3.0.x?
<bean id="photosetAddController" class="com.xyz.web.PhotosetAddController"
p:photosetManager-ref="photosetManager"
p:photosetTypeManager-ref="photosetTypeManager"
p:stateManager-ref="stateManager" >
<property name="validator">
<bean class="com.xyz.form.PhotosetAddValidator" />
</property>
<property name="formView" value="photosetadd" />
<property name="successView" value="redirect:/photoset" />
</bean>
Any pointers are greatly appreciated.
As skaffman noted - your code will work fine without any modifications. I'll answer your questions in short:
You can use #Resource(name="beanName") for name-based injection. But autowiring is also a good option. Either #Autowired, or #javax.inject.Inject. Note that you can use #Qualifier("name") to differentiate between beans with the same interface/base class. You can even use the javax.inject qualifiers (read about all these in the docs)
interceptor mappings can stay the same
There is #InitBinder, which denotes the initBinder method. I can't tell about the other.

Resources