Spring MVC 3.2 - XStreamAlias Ignored - spring-mvc

Person.java:
#XStreamAlias("person")
public class Person {
#XStreamAlias("id")
private Long personProfileId;
private String lastName;
private String firstName;
private String middleName;
private String nameSuffix;
private String namePrefix;
// etc ...
}
Spring configuration:
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="ignoreAcceptHeader" value="true" />
<property name="useJaf" value="false" />
<property name="defaultContentType" value="application/xml" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="contentNegotiationManager" ref="contentNegotiationManager" />
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
</constructor-arg>
</bean>
</list>
</property>
</bean>
<mvc:annotation-driven
content-negotiation-manager="contentNegotiationManager" />
A call to http://mycompany.com:8080/myapp/persons?format=xml returns:
<?xml version="1.0" encoding="UTF-8"?>
<list>
<com.example.myapp.model.Person>
<personProfileId>1</personProfileId>
<lastName>McCartney</lastName>
<firstName>James</firstName>
<middleName>Paul</middleName>
</com.example.myapp.model.Person>
<com.example.myapp.model.Person>
<personProfileId>2</personProfileId>
<lastName>Lennon</lastName>
<firstName>John</firstName>
<middleName>Winston</middleName>
</com.example.myapp.model.Person>
<com.example.myapp.model.Person>
<personProfileId>3</personProfileId>
<lastName>Starkey</lastName>
<firstName>Richard</firstName>
</com.example.myapp.model.Person>
<com.example.myapp.model.Person>
<personProfileId>4</personProfileId>
<lastName>Harrison</lastName>
<firstName>George</firstName>
</com.example.myapp.model.Person>
</list>
I would expect it to return:
<?xml version="1.0" encoding="UTF-8"?>
<list>
<Person>
<id>1</id>
<lastName>McCartney</lastName>
<firstName>James</firstName>
<middleName>Paul</middleName>
</Person>
<Person>
<id>2</id>
<lastName>Lennon</lastName>
<firstName>John</firstName>
<middleName>Winston</middleName>
</Person>
<Person>
<id>3</id>
<lastName>Starkey</lastName>
<firstName>Richard</firstName>
</Person>
<Person>
<id>4</id>
<lastName>Harrison</lastName>
<firstName>George</firstName>
</Person>
</list>
It seems like XStream is correctly being called to marshall the object to XML, but that the #XStreamAlias annotations are being ignored. Is there some further configuration needed to get this to work?

I was trying to figure out this same thing (though with a Spring Boot project) and found an alternative: autodetectAnnotations.
xstreamMarshaller.setAutodetectAnnotations(true);
See this project, add the above line to the Application.java.

Figured it out. The annotated classes need to be explicitly identified to the XStreamMarshaller.
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="annotatedClasses">
<array>
<value>com.example.myapp.model.Person</value>
</array>
</property></bean>
</constructor-arg>
</bean>
</list>
</property>

As per XStream documentation https://x-stream.github.io/annotations-tutorial.html
you have to use xstream.processAnnotations(MyPOJO.class);

Related

Spring+Quartz Fire job execution only if previous has finished

I'm using SpringMVC (4.x) along with Quartz (2.x). I'm setting a bean defnition file to fire a simple job, but wnat to make sure that the job is only fired if the previous execution of that job has already finished. Is there a parameter I can inform to SimpleTriggerFactoryBean in order to avoid concurrent execution?
By using the repeatInterval property, won't I fire simultaneous jobs?
My Quartz Bean Definition XML
<bean id="autoPusherJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="br.teste.AutoMessagePusherJob" />
<property name="jobDataAsMap">
<map>
<entry key="userName" value="SystemCronJob"/>
<entry key="message">
<bean class ="br.teste.model.Message"/>
</entry>
</map>
</property>
<property name="durability" value="true" />
</bean>
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="autoPusherJob" />
<property name="startDelay" value="1000" />
<property name="repeatInterval" value="1000" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="autoPusherJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
</bean>
Your job class needs to be annotated with the DisallowConcurrentExecution annotation.

How can a Spring Webflow application be configured to use Xslt to render its viewstates

I would like my Spring Webflow app to render its views using XSLT. I managed to get a pure Spring MVC app to render with xslt by configuring an XSLTviewresolver and a controller method that returned an already prepared xml as a source.
But I'm not sure how to apply that to the webflow app.
I've added the configuration for the XSLT view resolver and set the view state to the xsl, then I call the controller method that returns the xml source in the on-render of the view state.So far I only get the xsl back as the output and not the transformed xml or even the raw xml.
EDIT
flow.xml-full
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
<view-state id="messageChoice" view="start1">
<transition on="chooseA" to="messageA"/>
<transition on="chooseB" to="messageB"/>
</view-state>
<view-state id="messageA" view="messageA">
<transition on="start" to="messageChoice"/>
</view-state>
<view-state id="messageB" view="xsltview">
<on-render>
<evaluate expression="sampleController.viewXSLT(externalContext.getNativeRequest(),externalContext.getNativeResponse())" result="requestScope.xmlSource"/>
</on-render>
<transition on="start" to="messageChoice"/>
</view-state>
<end-state id="finish"/>
</flow>
controller-snippet
#RequestMapping(value="/viewxslt")
public ModelAndView viewXSLT(HttpServletRequest request,
HttpServletResponse response) throws IOException {
// builds absolute path of the XML file
String xmlFile = "/WEB-INF/xml/thexml.xml";
String contextPath = request.getSession().getServletContext().getRealPath(xmlFile);
String xmlFilePath = ""+contextPath + File.separator + xmlFile;
Source source = new StreamSource(new File(contextPath));
// adds the XML source file to the model so the XsltView can detect
ModelAndView model = new ModelAndView("xsltview");
model.addObject("xmlSource", source);
return model;
}
EDIT
flow-config-full
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<context:annotation-config />
<context:component-scan base-package="com.genkey.derek" />
<mvc:view-controller path="/start" />
<mvc:view-controller path="/messageHome" />
<mvc:resources location="/" mapping="/resources/**" />
<faces:resources />
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry" />
<property name="order" value="3" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean id="xsltviewresolver" class="org.springframework.web.servlet.view.xslt.XsltViewResolver">
<property name="order" value="1"/>
<property name="sourceKey" value="xmlSource"/>
<property name="viewClass" value="org.springframework.web.servlet.view.xslt.XsltView"/>
<property name="viewNames">
<array>
<value>xsltview</value>
</array>
</property>
<property name="prefix" value="/WEB-INF/xsl/" />
<property name="suffix" value=".xsl" />
</bean>
<bean id="viewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers">
<list>
<ref bean="xsltviewresolver"/>
<ref bean="faceletsViewResolver" />
</list>
</property>
</bean>
<bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".xhtml" />
<property name="order">
<value>2</value>
</property>
</bean>
<bean class="org.springframework.faces.webflow.JsfFlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-listeners>
<webflow:listener ref="facesContextListener"/>
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" >
<webflow:flow-location path="WEB-INF/flows/startFlow.xml"/>
</webflow:flow-registry>
<faces:flow-builder-services id="flowBuilderServices" view-factory-creator="viewFactoryCreator" development="true" />
<bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener"/>
</beans>

setting up an sql connection to run a spring-mvc project, using intelliJ

I've cloned a spring-mvc project to my computer and trying to get it running using intelliJ. It seems, according to this that I need to establish an SQL connection. Do I need to download mysql to my computer, create an account and enter that information in my connection.XML file (seen below)?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Data Source Setup -->
<bean id="hsqldataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql" />
<property name="username" value="example" />
<property name="password" value="example" />
</bean>
<bean id="mysqldataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.0.0.0:3306/dev" />
<property name="username" value="example" />
<property name="password" value="example" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>example/peer-review/domain/hibernatemapping/Division.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/Modality.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/Score.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/User.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/QaCase.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/Review.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/Exam.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/Patient.hbm.xml</value>
<value>example/peer-review/domain/hibernatemapping/Role.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
<property name="dataSource" ref="hsqldataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Dao Layer generic config-->
<bean id="abstractDaoTarget" class="example.peer-review.persistence.hibernate.GenericDAOHibernateImpl" abstract="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Dao Layer instances -->
<bean id="DivisionDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.DivisionDAOHibernateImpl" />
<bean id="ModalityDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.ModalityDAOHibernateImpl" />
<bean id="ScoreDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.ScoreDAOHibernateImpl" />
<bean id="UserDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.UserDAOHibernateImpl" />
<bean id="ReviewDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.ReviewDAOHibernateImpl" />
<bean id="QaCaseDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.QaCaseDAOHibernateImpl" />
<bean id="ExamDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.ExamDAOHibernateImpl" />
<bean id="PatientDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.PatientDAOHibernateImpl" />
<bean id="RoleDAO" parent="abstractDaoTarget" class="example.peer-review.persistence.hibernate.RoleDAOHibernateImpl" />
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://example.edu:1234" />
<property name="base" value="" />
<property name="userDn" value="cn=Test1" />
<property name="password" value="Test1" />
<property name="authenticationStrategy" ref="ldapAuthStrat" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
<bean id="ldapAuthStrat" class="org.springframework.ldap.core.support.ExternalTlsDirContextAuthenticationStrategy" />
</beans>
Your conf file contains the definition for two different datasources, hsql and mysql. hsql is an in memory db.
Mysql is standalone database application.
yes to connect to the mysql source, you need to download mysql and set up users/schema.

Custom Argument Resolver for ExceptionHandlerExceptionResolver

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>

i18n with Spring MVC, skip RequestMapping

I have set up i18n to my web app using Spring.It works fine.But I have a problem.When I click link to different language,from, lets say edit_user page. The request url is generated as '/edit_user.htm?lang=de'.Controller class receives this request and run editUser method based on #RequestMapping(value = { "edit_user" }). How to avoid this from happening.I just want my web app to be able to simply change the locale without reaching controller class methods when clicked on "change language links". My spring-config-servlet.xml is as following.
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:i18n/messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate" />
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="pretty" value="text/html" />
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
</constructor-arg>
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
....
</property>
<property name="defaultErrorView" value="errorPage" />
</bean>
Hm... Interesting.
UserController class receives this request:
en | de
for URL http://www.example.com/AppName/User/edit_user.htm?lang=de and run editUser method.
But you can change your links to:
EN | DE
and now when user click link to different language HomeController class receives request /?lang=de, web app change the locale and redirect user to the root page http://www.example.com/AppName/?lang=de.
Is this behavior acceptable for your application?
Otherwise I guess you have to filter request params for all controller classes if you want to find another solution.

Resources