I'm using Spring 3.2 and my Spring MVC controller generate JSON data (with jackson-databind-2.2.0). I would like to customize my JSON root name with #JsonRootName (com.fasterxml.jackson.annotation.JsonRootName) annotation, however, I could not figure out how to enable it with Spring configuration.
#JsonRootName("rootNameTest")
public class MyModel {
private String prop;
public String getProp() {
return prop;
}
public void setProp(String prop) {
this.prop = prop;
}
}
Here's my settings in sevlet-context.xml
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManager">
<constructor-arg>
<bean class="org.springframework.web.accept.ParameterContentNegotiationStrategy">
<constructor-arg>
<map>
<entry key="json" value="application/json"/>
</map>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
</list>
</property>
</bean>
Please help. Thanks.
Setbelow in com.fasterxml.jackson.databind.ObjectMapper
om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
om.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
this may be done by extending above Class with your custom and inject in org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
Related
My requirement is to redirection between two different apps in different JVMs. And also transfer data between the two. I tried using Flash Attributes, but in the controller, the attributes are null. I tried creating an interceptor also, but even there the flash attributes are null. Can anyone help me on how to pass attributes between two different applications?
Here is my code:
poc1 - calling application
dispatcher-servlet.xml
<context:component-scan base-package="controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean name="flashMapManager" class="org.springframework.web.servlet.support.SessionFlashMapManager" />
<mvc:annotation-driven />
</beans>
Controller.java
#RequestMapping(value = "add", method = RequestMethod.POST)
public String add(#ModelAttribute("customer") Customer customer,
final RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("customer", customer);
redirectAttributes.addFlashAttribute("message", "Added successfully.");
return "redirect:http://localhost:8080/poc2";
}
poc2 - called application
dispatcher-servlet.xml
<context:component-scan base-package="controller" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean name="flashMapManager"
class="org.springframework.web.servlet.support.SessionFlashMapManager" />
<!-- <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors"> <list> <ref bean="requestInterceptor" /> </list>
</property> </bean> -->
<bean id="requestInterceptor" class="RequestInterceptor" />
<mvc:annotation-driven />
<mvc:interceptors>
<ref bean="requestInterceptor" />
</mvc:interceptors>
</beans>
Controller.java
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(Model model, HttpServletRequest request,
HttpSession session) {
Map<String, ?> inputFlashMap = RequestContextUtils
.getInputFlashMap(request);
Customer cust1 = (Customer) model.asMap().get("customer");
Customer cust = (Customer) inputFlashMap.get("customer");
ModelAndView modelMap = new ModelAndView("showCustomer");
System.out.println("Calling controller");
return modelMap;
}
you can use this,
Using just redirectAttributes.addFlashAttribute(...) -> "redirect:..." worked as well, didn't have to "reinsert" the model attribute.
I'm trying to use a custom argument inside a method annotated with the ExceptionHandler in spring mvc 3.2 to handle an exception.
However I still get this exception when the method is executed:
java.lang.IllegalStateException: No suitable resolver for argument[1] [type=com.example.domain.CustomArgument]
The Controller method looks like:
#ExceptionHandler(IOException.class)
#ResponseBody
public Error handleIOException(IOException ex, CustomArgument customArgument) {
return new Error(customArgument.getMessage());
}
And I'm using the following xml config:
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.example.spring.CustomArgumentWebArgumentResolver" scope="singleton">
<constructor-arg ref="customArgumentService" />
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
<bean id="customArgumentService" class="com.example.service.CustomArgumentService" scope="singleton" />
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver" scope="singleton">
<property name="customArgumentResolvers">
<list>
<bean class="com.example.service.CustomArgumentService" scope="singleton">
<constructor-arg ref="customArgumentService" />
</bean>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" scope="singleton">
<property name="defaultErrorView" value="forward:/error" />
</bean>
And I believe mvc:annotation-driven is already assigning a ExceptionHandlerExceptionResolver, so how can I add the customArgumentResolver to that.
Any help would be greatly appreciated.
For several ExceptionResolvers try using HandlerExceptionResolverComposite. Something like this:
<bean class="org.springframework.web.servlet.handler.HandlerExceptionResolverComposite">
<property name="exceptionResolvers">
<list>
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
<constructor-arg ref="exceptionHandlerExceptionResolver" />
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<constructor-arg ref="simpleMappingExceptionResolver" />
</bean>
</list>
</property>
<property name="order" value="0"/>
</bean>
I am trying to enhance my spring-enabled web-app's security using Apache Shiro and am thus configuring filterchain definitions into a spring-configured file.
How do i achieve the equivalent of
#Controller
#RequestMapping("/mywebapp")
// #RequiresAuthentication (is this possible ? wish i could do this !)
public class MyWebAppController {
#RequiresRoles(value={"Role1","Role2","Role3"},logical=Logical.OR)
#RequestMapping(value="/home", method = RequestMethod.GET)
public String home() { return .. }
and my spring-config file contains this :
assume that my dispatcherservlet is mapped to /rest/*
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/rest/secure/windowslogin"/>
<property name="successUrl" value="/mywebapp/rest/menu"/>
<property name="unauthorizedUrl" value="/mywebapp/rest/unauthorized"/>
<property name="filters">
<util:map>
<entry key="anon">
<bean class="org.apache.shiro.web.filter.authc.AnonymousFilter"/>
</entry>
<entry key="authc">
<!-- why is this not invoked ? -->
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter">
</bean>
</entry>
<entry key="roles">
<bean class="org.apache.shiro.web.filter.authz.RolesAuthorizationFilter"/>
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/rest/secure/** = anon
/rest/mywebapp/** = authc, roles[Role1,Role2,Role3]
</value>
</property>
</bean>
In the code above i need a logical.OR kind of mapping to the /rest/mywebapp/** using the roles mentioned. This is possible via shiro annotations and it works but rather than specifying at every method i would rather handle it here (since i dont think shiro supports class level annotations yet ?) .
Is this possible ?
Also on a side note why is the authc filter not invoked ?
( for now we assume that the windows login can serve as authentication, using shiro only for authorization )
home page = meta refresh to /rest/secure/windowslogin/
if within intranet -> login ...
else /rest/secure/login ... login page.
Is it because the loginurl is different ? How do i circumvent this ? Note that my realm's getAuthorizationInfo is invoked though using the roles[ .. ] part specified in the config file.. but i was assuming that there should be a check to see if the request is 'authc' ? (which probably means that the filter is invoked and SubjectUtils.getSubject() is checked for authentication). Am i missing something in the flow or configuration ?
This is how shiro-security.xml looks like.
<bean id="customFilter1" class="com.pkg.RolesAuthorizationFilter">
<property name="roles" value="ROLE1,ROLE3,ROLE5"></property>
</bean>
<bean id="customFilter2" class="com.pkg.RolesAuthorizationFilter">
<property name="roles" value="ROLE1,ROLE2,ROLE5,ROLE6"></property>
</bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/home" />
<property name="unauthorizedUrl" value="/unauthorized" />
<property name="filters">
<util:map>
<entry key="authc">
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/resources/** = anon
/login = anon
/logout = authc
/unauthorized = authc
/someurl/** = customFilter2
/** = customFilter1
</value>
</property>
</bean>
And this is RolesAuthorizationFilter class
package com.pkg;
import java.util.Arrays;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.log4j.Logger;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
public class RolesAuthorizationFilter extends AuthorizationFilter {
protected Logger logger = Logger.getLogger(this.getClass()
.getCanonicalName());
private String[] roles;
#Override
protected boolean isAccessAllowed(ServletRequest request,
ServletResponse response, Object mappedValue) throws Exception {
logger.info("= Roles = " + Arrays.toString(roles));
Subject subject = getSubject(request, response);
boolean allowAccess = false;
for (String role : roles) {
if (subject.hasRole(role)) {
logger.info("Authenticated role " + role);
allowAccess = true;
break;
}
}
return allowAccess;
}
public void setRoles(String[] roles) {
this.roles = roles;
}
}
I;m trying to create RSS feeds for my web site. I follow the tutorial from mkyong (http://www.mkyong.com/spring-mvc/spring-3-mvc-and-rss-feed-example/) which was quite useful. According to this tutorial i create a model class and the following class
public class CustomRssViewer extends AbstractRssFeedView{
#Override
protected void buildFeedMetadata(){
//some code
}
#Override
protected List<Item> buildFeedItems(){
//some code
}
}
And finally the controller class
#Controller
public class RssController {
#RequestMapping(value="/rssfeed", method = RequestMethod.GET)
public ModelAndView getFeedInRss() {
//set the RSS content
ModelAndView mav = new ModelAndView();
mav.setViewName("rssViewer");
mav.addObject("feedContent", items);
return mav;
}
}
According to the tutorial the View rssViewer belongs the class CustomRssViewer , so i need to write it at the dispatcher servlet the following lines of code:
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean id="rssViewer" class="com.mkyong.common.rss.CustomRssViewer" />
My problem is that i'm using apache tiles. So the rssViewer can not be recognised as i didn't enhanced it to the tiles definition. And i really don't know how can i do this. For example i need to write something as the following:
<definition name="rssViewer" template="?">
<put-attribute name="title" value=""/>
<put-attribute name="content" value=""/>
</definition>
At the template i don't know what to declare as well as at the put-attribute.Because until now at the template i use to declare the direction that a specific jsp exists. Something like this:
template="/WEB-INF/pages/mypage.jsp"
And also at the view-properties i don't know what should i declare.
Thanks in advance for any comment or response.
You should use a ContentNegotiatingViewResolver in conjuction with that example's BeanNameViewResolver. Just declare the order property of your already existing BeanNameViewResolver to be 1, and set the order property of the new ContentNegotiatingViewResolver to 0.
You should then configure the ContentNegotiatingViewResolver to use the appropriate View for RSS, and set the media type for RSS.
Here is an example from the Spring Docs:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
Note, they are using atom, not RSS, but the idea is the same. Also they do not set the order (which you should do).
I have added my own interceptor in spring portlet i.e.
<bean id="portletModeParameterHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping">
<property name="interceptors">
<list>
<ref bean="customInterceptor"/>
</list>
</property>
<property name="portletModeParameterMap">
...............
.......
</property>
<bean id="customInterceptor" class="com.xyz.CustomInterceptor"></bean>
And I have write CustomInterceptor class
class CustomInterceptor extends HandlerInterceptorAdapter implements ServletContextAware {
//#override
public boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) {
...............
............
}
}
This CustomInterceptor should get call for every request before controller call.
But CustomInterceptor not getting called by spring.
Is anything goes wrong over here?
Thank You.
I may be late for responding to you question but you need to use below code..
<bean id="customInterceptor" class="com.xyz.CustomInterceptor"></bean>
<bean class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="customInterceptor" />
</list>
</property>
</bean>