I created a basic Spring MVC / JPA / Hibernate app. I am trying to save a UserProfile entity to test if I can actualy persist it, but nothing gets saved and no exception is thrown either.
In the controller method I create a simple UserProfile (which is an #Entity) and I am sending that to a service method. The UserProfileServiceImpl class is annotated with #Service and the addUserProfile(UserProfile profile) method is annotated with #Transactional.
In the service method, all I do is call a DAO method (class annotated with #Repository). In the DAO method all I do is call entityManager.persist(object), with object being the user profile object.
Nothing gets written to the server log and the log level is at INFO.
Nothing appears in the Mysql query log (and I know the query log works)
The entityManager gets properly injected.
The datasource is properly initiated, because when I enter faulty credentials I get SQLExceptions.
I hope you can tell me what's wrong. I'll post some of my code and config files below.
The service method:
// The service method gets called from the controller.
// Its class is annotated with #Service
#Transactional(readOnly = false)
public void addUserProfile(UserProfile userProfile) {
userProfileDao.save(userProfile);
}
The Dao method:
// The save(T object) method is in the GenericDaoJpa class, which is the superclass
// of the UserProfileDaoJPA class that is referenced from the service.
// I have established that the entityManager is there and the object is a
// UserProfile. The #Repository annotation is on the child class UserProfileDaoJpa.
public void save(T object) {
entityManager.persist(object);
}
Main application-context.xml
<context:property-placeholder location="classpath*:**/*.properties"/>
<import resource="spring-jpa.xml"/>
The application-context-web.xml file
<mvc:annotation-driven />
<context:component-scan base-package="nl.codebasesoftware.produx" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
spring-jpa.xml
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${db.driverClassName}"
p:url="${db.url}" p:username="${db.username}" p:password="${db.password}"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>
persistence.xml
<persistence-unit name="mysqlPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
<!-- Needed to properly process #PersistenceContext -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
Somehow no SQL is sent to Mysql with this setup, but no exception is thrown either, so I have no idea what's going on. Hope you can help :)
i think you are missing transaction propagation at service. marking readonly=false just set session to auto flush. but setting up proper transaction propogation will make sure start of trnasaction and commit/rollback.
after removing mode="aspectj" it has started working because i think because of as per spring doc
The default mode "proxy" will process annotated beans to be proxied
using Spring's AOP framework (following proxy semantics, as discussed
above, applying to method calls coming in through the proxy only). The
alternative mode "aspectj" will instead weave the affected classes
with Spring's AspectJ transaction aspect (modifying the target class
byte code in order to apply to any kind of method call). AspectJ
weaving requires spring-aspects.jar on the classpath as well as
load-time weaving (or compile-time weaving) enabled. (See the section
entitled Section 6.8.4.5, “Spring configuration” for details on how to
set up load-time weaving.)
and probably you have not configured load time weaving
Ok, I got it. First I thought I found the answer here
Declarative transactions (#Transactional) doesn't work with #Repository in Spring
But after some more testing I found it was not the location of
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
but its contents.
After removing the mode="aspectj" attribute it started working! If anyone would like to comment why that is, please do.
Let me share my full setup with you. This is for Spring 3.1 with Hibernate 4. NOTE: for 'brevity' I only posted the contents of the configuration files, and omitted the outer tags <beans> and <persistence> and the namespace declarations. I removed spring-jpa.xml altogether and moved its contents into application-context.xml.
Contents of web.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<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>My Spring MVC web application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:**/application-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>produxDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:**/application-context-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>produxDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Contents of application-context.xml:
<!-- main setup -->
<context:property-placeholder location="classpath*:**/*.properties"/>
<context:annotation-config/>
<context:component-scan base-package="nl.codebasesoftware.produx.domain" />
<context:component-scan base-package="nl.codebasesoftware.produx.service" />
<context:component-scan base-package="nl.codebasesoftware.produx.dao" />
<!-- Data and JPA setup -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${db.driverClassName}"
p:url="${db.url}" p:username="${db.username}" p:password="${db.password}"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>
Contents of application-context-web.xml:
<mvc:annotation-driven />
<context:component-scan base-package="nl.codebasesoftware.produx.controller" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
Contents of webapps/META-INF/persistence.xml
<persistence-unit name="mysqlPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<!-- <property name="hibernate.hbm2ddl.auto" value="create-drop"/> -->
</properties>
</persistence-unit>
<!-- Needed to properly process #PersistenceContext which injects the entity manager -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
Contents of environment.properties:
db.url=jdbc:mysql://localhost:3306/yourDatabaseName
db.driverClassName=com.mysql.jdbc.Driver
db.username=yourUsername
db.password=yourPassword
Related
I'am working on a small Spring powered application. I have a form with some text fields , but after POST, at server side, this fields content loses for example ś, ć chars . They become replaced by their utf-8 code: 'ó'; etc. They are saved in this way in MySql db. When i get this data from db and display they in the freemarker based view layer they are displayed correctly. But how can I get proper chars at server-side ?
I added this in the head of my template
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
I setted encoding for the database
I configured Hibernate like this:
persistence.xml
<persistence-unit name="evPU">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.connection.CharSet">utf8</property>
<property name="hibernate.connection.characterEncoding">utf8</property>
<property name="hibernate.connection.useUnicode">true</property>
</properties>
</persistence-unit>
context.xml
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/*****?characterEncoding=UTF-8" />
<property name="username" value="****" />
<property name="password" value="****" />
</bean>
Finally, I used a filter
web.xml
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
But nothing of this solved my problem. Someone can give me a clue?
Solved
I added this property in viewResolver bean at context.xml
<property name="contentType" value="text/html;charset=UTF-8" />
Make sure the form accepts UTF-8 with:
<form accept-charset="UTF-8">
Remove the character encoding filter in web.xml.
Well, I have posted following question on Shiro's forum for 1 week but no response until now.
I am just trying to use Shiro with a simple Spring application. The security manager is defined as DefaultWebSecurityManager which set session manager as ServletContainerSessionManager by default and it works for me. However, after I changed the session manager to DefaultWebSessionManager which means I want to use Shiro's native session, it not works on Chrome. I dug out some following information:-
When using DefaultWebSessionManager, Shiro tries to get session id from request cookie. The logic SimpleCookie is looping all request cookies and return when a cookie's name is 'JSESSIONID'. However, in the requests come from Chrome, there are 2 cookies with name 'JSESSIONID'. The value of the first one is different with 'requestedSessionid' in request and the other one equals. That result in a new redirect to login page after authentication successfully. To make it simple, the process now is: access any address -> redirect to login page by Shiro -> submit principals and credentials -> authentication successfully and redirect to home page by Shiro -> a new request comes and found another session id which is not cached in Shiro, result in a InvalidSessionException in resolveSession method in DefaultSecurityManager -> redirect back to login
page.
When using ServletContainerSessionManager, since the session id is come from request.getSession(false), the session could be found after redirect.
My question is if this is a defect or anything configurations or codes can fix this problem? Note only Chrome fires this problem. I guess it's about Chrome's cache but can you explain more?
Below is the necessary sources for you to replicate:-
web.xml
<listener>
<listener-class>test.shiro.framework.WebSessionListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</context-param>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/controller/*</url-pattern>
</servlet-mapping>
spring-servlet.xml:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login.jsp"/>
<property name="successUrl" value="/home.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<property name="filterChainDefinitions">
<value>
/** = authc
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm" />
<property name="sessionManager">
<bean class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"></bean>
</property>
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean id="myRealm" class="org.apache.shiro.realm.text.TextConfigurationRealm">
<property name="userDefinitions">
<value>
huzj=12345678,authc
guodg=12345678,operator
sadd=12345678,guest
</value>
</property>
<property name="roleDefinitions">
<value>
authc=*
operator=book:*
guest=book:view:*
</value>
</property>
</bean>
Feb 18 UPDATE:
A further testing shows that the problem only occured when I tried to change from ServletContainerSessionManager to DefaultWebSessionManager. I guess chrome records a junk cookie in this situation by mistake.
After all I tried #paulochf's solution and it does work. I debugged again and believe you got the point. Many thanks!
At my work, we had the very same problem, but we resolved it.
Using Google Chrome, the application could not keep the session because it's ID changed almost at each request made. Meanwhile, Firefox didn't have it. The guy who had turned DefaultWebSessionManager on used an example from the web, where it set the cookie name as "cookie".
He resolved changing the name of the cookie to another, for example,
cookie = org.apache.shiro.web.servlet.SimpleCookie
cookie.name = your.cookie
cookie.path = /
sessionManager.sessionIdCookie = $cookie
I expect this works to you.
Your solution still works. Current environment : Shiro 1.2.3 , Chrome Version 42.0.2311.90 (64-bit), Linux OS.
For those who configure Shiro via Spring, here's how to override the JSESSIONID as the default cookie name (to "JSESSID" in this case).
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="globalSessionTimeout" value="..." />
<property name="sessionListeners">
<util:list>
<ref bean="..." />
</util:list>
</property>
<property name="sessionIdCookie">
<bean class="org.apache.shiro.web.servlet.SimpleCookie">
<property name="name" value="JSESSID" />
</bean>
</property>
</bean>
I have a problem that can not be resolved on the configuration of ObjectMapper. I need to configure it to ignore those parameters that do not have my POJO...so easy but I configured a thousand different ways and I can not make it work.
my servlet.xml
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" >
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="featuresToDisable">
<array>
<util:constant
static-field="com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES"/>
</array>
</property>
</bean>
</property>
</bean>
I have also tried to extend the class ObjectMapper but I get the same results. I see the mapper is configured correctly but i hope MappingJackson2HttpMessageConverter receives a different instance of ObjectMapper. I Dont know what else to do to make me ignore the parameters globally.
When I make a request with a parameter that should be ignored (not present on the POJO) gives a syntax error in the request.
Im using:
Spring 3.2.0
jackson 2.1.2
Best regards and thank´s
Try
<!--
Implement a custom ObjectMapper and initialize the features you needed
eg. FAIL_ON_UNKNOWN_PROPERTIES
-->
<bean id="jacksonObjectMapper" class="com.sample.CustomObjectMapper"/>
<!-- Replace Spring's default message converter -->
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="jacksonObjectMapper"/>
</mvc:message-converters>
</mvc:annotation-driven>
Solution tested on Spring 3.2.18.RELEASE and Jackson 2.7.5.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<bean id="jacksonObjectMapper"
class="com.fasterxml.jackson.databind.ObjectMapper" />
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonObjectMapper" />
<property name="targetMethod" value="configure" />
<property name="arguments">
<list>
<value
type="com.fasterxml.jackson.databind.DeserializationFeature">FAIL_ON_UNKNOWN_PROPERTIES</value>
<value>false</value>
</list>
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
I have a custom MessageConverter registered in spring with the following configuration:
<bean id="jsonHttpMessageConverter" class="com.eventwiz.web.util.ServiceResponseHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="jsonHttpMessageConverter"/>
</util:list>
</property>
</bean>
However, it's not being called as I confirmed that with a breakpoint in my code. ServiceResponseHttpMessageConverter subclasses MappingJacksonHttpMessageConverter and overrides writeInternal() method. I've even tried overriding MessageConverter.supports() just to see if that was being called and it wasn't. Any ideas what's going on?
The issue, as was found based on an answer from the author was the <mvc:annotation-driven/> tag which registers its own handlerAdapter, so if another handlerAdapter is added to the Spring MVC configuration file with converters added to this adapter, the custom adapters will not take effect. The fix is to either register the httpMessageConverters through <mvc:message-converters... tag under <mvc:annotation-driven or removing <mvc:annotation-driven and having the custom handleradapter with the httpmessageconverter registered under it.
I cant get Spring's JSON support working. In my spring-servlet.xml file i have included following lines:
<mvc:annotation-driven/>
<context:component-scan base-package="my.packagename.here" />
<context:annotation-config />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
I have also downloaded jackson libraries and added them to my eclipse project and also to WEB-INF/lib folder. When sending request to controller with jQuery getJSON method i get following errors:
javax.servlet.ServletException: Servlet.init() for servlet dispatcher threw exception
java.lang.NoClassDefFoundError: org/codehaus/jackson/JsonProcessingException
java.lang.ClassNotFoundException: org.codehaus.jackson.JsonProcessingException
What do you think is the problem. I'm guessing it has something to do with my spring-servlet.xml file. I can paste entire error log, if you need.
For Jackson v2 jars, class to be used for bean should be
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
For older jackson version, org.springframework.http.converter.json.MappingJacksonHttpMessageConverter is ok. Make sure the jar files are added to the project library.
The answer of anshul tiwari partially captures the problem. Here is a more complete answer ...
When Jackson made it to version 2.0, the core library got changed from jackson-core-asl-x.x.x.jar to jackson-core-x.x.x.jar. With that, the paths changed. In version 1, org.codehaus.jackson was the path. In version 2, it is in com.fasterxml.jackson.core if you were to open up the jar file.
Now if you have the libraries of version 2 and you are seeing the org.codehaus.jackson ClassNotFoundException, it means that there is a mixing of versions. Some code is expecting v1 but you have provided v2. This is certainly possible when using Spring so you have to be careful to choose the correct jar file for your code.
EDIT
In fact, looking at 3.2 Spring source code, org.springframework.http.converter.json.MappingJacksonHttpMessageConverter still references the org.codehaus stuff so this is a case where Spring source code needs to import the correct path and there is nothing you the developer can do to use jackson 2.
JsonProcessingException is part of the jackson-core-asl-x.x.x.jar. Make sure that it's part of your classpath.
Just to complement anshul tiwari answer, the bean tag should go inside mvc:annotation-driver:
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.ResourceHttpMessageConverter" />
<!-- <bean -->
<!-- class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"
/> -->
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<!-- <bean -->
<!-- class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"
/> -->
</mvc:message-converters>
</mvc:annotation-driven>
Use it Like below : Hope it will work..
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"
default-lazy-init="true">
<context:component-scan base-package="com.vc.bmp.resource" />
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<!-- property name="prefixJson" value="true" />
<property name="supportedMediaTypes" value="application/json" /-->
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="serializationInclusion">
<value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>