Spring + Hibernate + H2 Embedded DB. How is the data saved? - spring

Im new to embedded databases but I got it running at least. What confuses me is that my data is not saved between runs. I mean wouldn't that be nice for testing? I don't wanna add data to my database every time i run the application
So I searched for a way to do this and I found that I shall configure a hibernate connection URL which I tried like this
props.put("hibernate.connection.url", "jdbc:h2:~/test");
in my HibernateConfiguration.java. Without success though, no errors but also nothing saved, and I did not find that test file that should be created from that URL. (Running windows and checked my user folder)
I also saw that its possible to do like this
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:db-schema.sql"/>
<jdbc:script location="classpath:db-test-data.sql"/>
</jdbc:embedded-database>
And execute the scripts every time i run the application, but the thing is that I want hibernate to handle all the creating of tables etc.
How is this normally done?
I searched for some hours now but haven't still got it.
Ps. if it's needed i'll post all my configs.
Edit:
Updated my question to contain focus on one question and included my configs.
HibernateConfiguration.java
package com.courseinfo.project;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.dialect.H2Dialect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import com.courseinfo.project.model.Course;
#Configuration
public class HibernateConfiguration {
#Value("#{dataSource}")
private DataSource dataSource;
#Bean
public AnnotationSessionFactoryBean sessionFactoryBean() {
Properties props = new Properties();
props.put("hibernate.dialect", H2Dialect.class.getName());
props.put("hibernate.format_sql", "true");
props.put("hibernate.connection.url", "jdbc:h2:~/test");
AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
bean.setAnnotatedClasses(new Class[]{Course.class});
bean.setHibernateProperties(props);
bean.setDataSource(this.dataSource);
bean.setSchemaUpdate(true);
return bean;
}
#Bean
public HibernateTransactionManager transactionManager() {
return new HibernateTransactionManager( sessionFactoryBean().getObject() );
}
}
servlet-context.xml where i only added the embedded database tag.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd"
default-lazy-init="true">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.courseinfo.project" />
<jdbc:embedded-database id="dataSource" type="H2"/>
</beans:beans>
There of course also a pom where i got all dependencies but i don't think that is necessary.
I'm creating a object (Course.java) and saving that to the db, that's fine and i can load it again. But when I change my code and the application is reloaded the object doesn't exist anymore.
Edit2: I'm adding data like this.
Binding a session factory.
#Autowired
private SessionFactory sessionFactory;
Adding a my Course object to the database like this.
Course course = new Course();
course.setCourseId("IDA512");
Session s = sessionFactory.openSession();
s.saveOrUpdate(course);
s.flush();
s.clear();
Course course2 = (Course) s.get(Course.class, "IDA511");
s.close();
This works fine and i can get that course.
However, when I run the application next time there is no course with id IDA511 and i getting a null pointer exception. Does this mean that the course is only saved in the session maybe? hum

Since you are running your application on Windows, perhaps the home directory is not found using the tilde '~' operator.
Try giving your hibernate.connection.url property an absolute path eg. "C:\test" and check in that folder when you run the application to see if H2 creates a file for you.

For saving h2 in user directory as a file you can use
jdbc:h2:file:~/rmdb;AUTO_SERVER=TRUE;
and if you application not running, you can connect to it for example from intellij IDEA db util.

Related

Benefits of JavaConfig over XML configurations in Spring?

Earlier the configurations used to be in hard coded in the code, later it was externalized to .property files (for sake of avoiding hard coded values, avoiding changing code for the sake of changing configurations..etc) then it moved to XML (for sake of being more standardized, error free..etc)
Now, while reading about #Configuration in Spring 3 , looks like we are again moving back to the initial approach.
Why would we want to hard-code configurations in the code rather than
having it externalized ?
There are some advantages
Java is type safe. Compiler will report issues if you are
configuring right bean class qualifiers.
XML based on configuration can quickly grow big. [Yes we can split
and import but still]
Search is much simpler, refactoring will be bliss. Finding a bean
definition will be far easier.
There are still people who like XML configuration and continue to do it.
References:
Java configuration advantages
Some more reasons
Correct answer was given here, Other-than that answer, I give one more point
According to the Spring 5 reference
XML-based metadata is not the only allowed form of configuration
metadata. The Spring IoC container itself is totally decoupled from
the format in which this configuration metadata is actually written.
These days many developers choose Java-based configuration for their
Spring applications.
it means nowadays, people are moving towards java based config
for example: Spring web-mvc config in xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="controller" />
<context:component-scan base-package="dao" />
<context:component-scan base-package="service" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
and same config in java based style
#Configuration
#EnableWebMvc
#ComponentScans({
#ComponentScan("controller"),
#ComponentScan("dao"),
#ComponentScan("service")
})
public class WebMVCConfig implements WebMvcConfigurer {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
what is easy to understand? Obviously, the Java-based config is easy to understand.
people who write codes and others can easily understand java code than XML. and you do not need to know about XML if you only know Java.

Spring configuration issues not easy to find solution for

I have found several really awkward problems which took me 3hr+ to resolve. I was wondering if anyone could explain me why this is the case. I believe both of them belong to the very much same context so I have two questions. I hope reader will have patience as for me this is both intimidating and interesting behavior of sf.
I only know the error and resolution, but not satisfied until I understand:
Guidance I follow: Have one configuration file - use package scan inside of your root customConfig only(declared via mapping in web.xml), make sure servlet-context.xml only scans controllers' package. All other context files import via import directive at the very beginning of your customConfig.
1.1 Error if you do it other way: Dependency injection(of various components) will dramatically fail with multiple overlapping config package scanning.
1.2 Error if you do it other way: Transaction during service request of transactionManager in context with entityManagerFactory will fail if servlet-context.xml scans the same package. (i.e. same service package as your customConfig scans)
2: LocaleChangeInterceptor can only be declared in servlet-context - won't work in custom root configuration, reason unknown(doesn't work even if adding package scan for controllers package inside customConfig however now funny bit - SessionLocaleResolver on the other hand will work ok if defined in custom config! )
Q1: So it is me to blame who as human was mistakenly adding overlapping context-component package scan or it would be logical for Spring to resolve these collisions? Or they should be resolved but it doesn't work for me for some reason?
I observed fellow developer and smiled when he told it is best not to touch spring configuration nor try to improve it nor try to update it. I smiled, now I clearly don't(I now find myself intimated by this sf config violence), after all of this do you think it is ok to place everything inside just a single configuration file like servlet-context.xml ?
Q2: What is the magic behind LocaleChangeInterceptor, I've spent around 5 hours fixing it until just moved in "try-and-fail" mood it into servlet-context and it worked.
Second is a pure mystery to solve. Nothing fancy inside customConfig
<?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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!--
<import resource="securityContext.xml"/> -->
<import resource="jpaContext.xml"/>
<context:annotation-config />
<context:component-scan base-package="com.org.app" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en_GB" />
</bean>
<mvc:interceptors>
<bean
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
p:paramName="lang" />
</mvc:interceptors> ...
After firing ?lang=locale_LOCALE request nothing will happen - no error, no indication , app will load successfully and page will just be reloaded under the same locale.
However placing this interceptor code inside servlet-context.xml below will resolve on locale request successfully.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<context:component-scan base-package="com.org.app.controller" />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<interceptors>
<beans:bean
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
p:paramName="lang" />
</interceptors>
</beans:beans>
Your LocalChangeInterceptor and LocaleResolver must be defined in the servlet-context.xml. <context:annotation-driven /> is already implied by the use of <context:component-scan />
In your root context you are also scanning for #Controller you need to exclude them.
<context:component-scan base-package="com.org.app">
<context:exclude-filter type="annotation" value="org.springframework.stereotype.Controller" />
</context:compoment-scan>
Basically all the web related things (and the things which are used by the DispatcherServlet) must be loaded by the DispatcherServlet. Due to its nature it will only look into its own local application context for the beans it needs instead of in its parents.
The reason for this is that you can have multiple DispatcherServlets each with its own configuration, this would break if it would load the configuration from the root application context.

I can use properties in Spring servlet context, but not #Value annotation inside #Controller

*-servlet.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<context:property-placeholder location="classpath*:spring.properties" />
<context:component-scan base-package="com.my.path" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
com.my.path.MyController
#Controller
public class MyController {
#Value("${my.property}")
private String myProperty;
#RequestMapping("/my/path")
public String default(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws Exception {
// Any reference to myProperty above is null...
return "view";
}
}
I do have other beans defined by ID in my servlet context that use the same system property I'm trying to add to my controller via the Value annotation. I know they are present and with the right values. So I'm not sure why I just can't get the annotation to work.
Take a look at this answer. Do you happen to have more XML Spring contexts? Is the component-scan defined on the same Spring config as the property-placeholder as shown above?
After reviewing just about every tutorial I could for a day I realized this has to be some sort of classloader issue. So I reviewed my packaging structure, which is an EAR containing a WAR. Sure enough I had two spring bean jars of identical versions, one in EAR/lib and the other in WAR/WEB-INF/lib. Apparently the properties were picked up in the EAR, but the post processing was happening in the WAR (or something like that). So by sorting that out, and getting duplicate JARs out of the WAR it is now fixed.

For web MVC Spring app should #Transactional go on controller or service?

For WebApplicationContext, should I put #Transactional annotations in the controller or in services? The Spring docs have me a bit confused.
Here is my 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="WebApp_ID" version="2.5">
<display-name>Alpha v0.02</display-name>
<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>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Here is my application-context.xml defining a spring dispatcher servlet:
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:annotation-config />
<mvc:annotation-driven />
<tx:annotation-driven />
<context:component-scan base-package="com.visitrend" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/postgres" />
<property name="user" value="someuser" />
<property name="password" value="somepasswd" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:test.hibernate.cfg.xml" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
Here's a service interface:
public interface LayerService {
public void createLayer(Integer layerListID, Layer layer);
}
Here's a service implementation:
#Service
public class LayerServiceImpl implements LayerService {
#Autowired
public LayerDAO layerDAO;
#Transactional
#Override
public void createLayer(Integer layerListID, Layer layer) {
layerDAO.createLayer(layerListID, layer);
}
}
And here's my controller:
#Controller
public class MainController {
#Autowired
private LayerService layerService;
#RequestMapping(value = "/addLayer.json", method = RequestMethod.POST)
public #ResponseBody
LayerListSetGroup addLayer(#RequestBody JSONLayerFactory request) {
layerService.createLayer(request.getListId(), request.buildLayer());
return layerService.readLayerListSetGroup(llsgID);
}
}
The Spring documentation has me a bit confused. It seems to indicate that using a WebApplicationContext means only controllers will be investigated for #Transactional annotations and not services. Meanwhile I see tons of recommendations to make services transactional and not controllers. I'm thinking that using <context:component-scan base-package="com..." /> in our spring-servlet.xml above so that it includes the services packages means the services are part of the context, and therefore will be "investigated" for transactional annotations. Is this accurate?
Here's the Spring documentation blurb that got me confused:
#EnableTransactionManagement and only looks
for #Transactional on beans in the same application context they are
defined in. This means that, if you put annotation driven
configuration in a WebApplicationContext for a DispatcherServlet, it
only checks for #Transactional beans in your controllers, and not your
services.
Further, is there any performance implications or "badness" if I define a controller method as transactional, and it calls a transactional method in a another class? My hunch is no, based on the documentation, but would love validation on that.
There is no requirement for whether the #Transactional annotation should go on a Controller or on a Service, but typically it would go on a Service that would perform the logic for one request that logically should be performed within one ACID transaction.
In a typical Spring MVC application, you would have, minimally, two contexts: the application context and the servlet context. A context is a sort of configuration. The application context holds the configuration that is relevant for your entire application, whereas the servlet context holds configuration relevant only to your servlets. As such, the servlet context is a child of the application context and can reference any entity in the application context. The reverse is not true.
In your quote,
#EnableTransactionManagement and only looks for #Transactional on beans in the same application context they are defined in. This means that, if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet, it only checks for #Transactional beans in your controllers, and not your services.
#EnableTransactionManagement looks for #Transactional in beans in packages declared in the #ComponentScan annotation but only in the context (#Configuration) they are defined in. So If you have a WebApplicationContext for your DispatcherServlet (this is a servlet context), then #EnableTransactionManagement will look for #Transactional in classes you told it to component scan in that context (#Configuration class).
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = "my.servlet.package")
public class ServletContextConfiguration {
// this will only find #Transactional annotations on classes in my.servlet.package package
}
Since your #Service classes are part of the Application context, if you want to make those transactional, then you need to annotate your #Configuration class for the Application Context with #EnableTransactionManagement.
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = "my.package.services")
public class ApplicationContextConfiguration {
// now this will scan your my.package.services package for #Transactional
}
Use your Application Context configuration with a ContextLoaderListener and your Servlet Context configuration when instantiating your DispatcherServlet. (See the javadoc for a full java based config, instead of xml, if you aren't doing it already.)
Addendum: #EnableTransactionManagement has the same behavior as <tx:annotation-driven /> in a java configuration. Check here for using ContextLoaderListener with XML.
The Service is the best place for putting transactional demarcations. The service should hold the detail-level use case behavior for a user interaction, meaning stuff that would logically go together in a transaction. Also that way a separation is maintained between web application glue code and business logic.
There are a lot of CRUD applications that don't have any significant business logic, for them having a service layer that just passes stuff through between the controllers and data access objects is not useful. In those cases you could get away with putting the transaction annotation on the data access objects.
Putting the transactional annotation on the controller can cause problems, see [the Spring MVC documentation][1], 17.3.2:
A common pitfall when working with annotated controller classes
happens when applying functionality that requires creating a proxy for
the controller object (e.g. #Transactional methods). Usually you will
introduce an interface for the controller in order to use JDK dynamic
proxies. To make this work you must move the #RequestMapping
annotations, as well as any other type and method-level annotations
(e.g. #ModelAttribute, #InitBinder) to the interface as well as the
mapping mechanism can only "see" the interface exposed by the proxy.
Alternatively, you could activate proxy-target-class="true" in the
configuration for the functionality applied to the controller (in our
transaction scenario in ). Doing so indicates
that CGLIB-based subclass proxies should be used instead of
interface-based JDK proxies. For more information on various proxying
mechanisms see Section 9.6, “Proxying mechanisms”.
The transaction propagation behaviors that you set up on the attributes decide what happens when a transactional method calls another transactional method. You can configure it so that the method called uses the same transaction, or so that it always uses a new transaction.
By having multiple calls to your service in the example code you're defeating the transactional purpose of the service. The different calls to your service will execute in different transactions if you put the transactional annotations on the service.
Sometimes it is very convenient to have #Transactional controller methods, especially when performing trivial operations using Hibernate. To enable this using XML configuration, add this to your dispatch-servlet.xml:
<beans ...
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="...
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
..
</beans>
The purpose of proxy-target-class is to use the CGLIB proxies which are required for AOP on controllers to work. If you don't add this, you'll get an error when starting up. Also, if you have any final methods in your controllers, note that they cannot be proxied (in particular, made transactional), and you will also get a warning from CGLIB for each of these methods, when starting up.

Load time weaving in grails

I'm trying to use load time weaving in a Grails project in order to be able to serialize and deserialize an object and to have automatic injection of spring dependencies. After some searching I found an easy example and that seems to work as expected. But after applying the same configuration to a simple Grails project I get a lot of errors. For example:
[TomcatInstrumentableClassLoader#413a2870] error at org/springframework/web/servlet/theme/AbstractThemeResolver.java::0 class 'org.springframework.web.servlet.theme.AbstractThemeResolver' is already woven and has not been built in reweavable mode
To test this I created a new grails project and changed the applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:spring-configured />
<context:load-time-weaver aspectj-weaving="autodetect" weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
In this file I also created a new bean:
<bean class="be.testweaving.Person" scope="prototype">
<property name="name" value="Timon"/>
</bean>
This defines a prototype for the Person class and injects the value Timon into the name property.
I package this as a war using grails war and deploy this on a tomcat server. This tomcat has the org.springframework.instrument.tomcat-3.0.5.RELEASE.jar in his lib directory and after the deployment I see a huge list of the errors I mentioned above.
Has anyone been able to configure load time weaving in Grails?
Why don't you just inject your property via metaclass?
class ExampleBootStrap {
def init = { servletContext ->
Person.metaClass.constructor = {
def person = BeanUtils.instantiateClass(Person)
person.name = "Timon"
person
}
}
}

Resources