I'm trying to configure apache tiles 2.2.2 EL support in Spring 3.1.
According to tiles documentation and from what I've found on google, this should work, but it doens't, instead, it throws NullPointerException
Tiles config:
<bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver">
<property name="order" value="1"/>
</bean>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/views/**/views-def.xml</value>
</list>
</property>
<property name="tilesProperties">
<props>
<prop key="org.apache.tiles.evaluator.AttributeEvaluator">
org.apache.tiles.el.ELAttributeEvaluator
</prop>
</props>
</property>
</bean>
Simple tiles definition:
<tiles-definitions>
<definition name="temp.test" template="/WEB-INF/views/temp/test.jsp">
<put-attribute name="test" expression="${test}" />
</definition>
</tiles-definitions>
test.jsp
<%--Works fine--%>
<h2>Called in jsp</h2>
<p>
<c:out value="${test}"/>
</p>
<%-- throws NullPointerException --%>
<h2>Inserted from tiles</h2>
<p>
<tiles:getAsString name="test"/>
</p>
Tiles libraries on cp:
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-api</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-core</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-el</artifactId>
<version>2.2.2</version>
</dependency>
use
<!--this works fine with expressions-->
<tiles:insertAttribute name="test" ignore="true" />
instead of
<!-- and this will throw NullPointerException if value is not provided-->
<tiles:getAsString name="test" ignore="true"/>
Had similar behavior with null pointer while playing with spring mvc 3.1.2.RELEASE and tiles 2.2.2. Check your xerxesImpl if is the latest 2.9.1. Also check your taglib as mentioned earlier also check your logging. These work fine together:
<org.slf4j.version>1.5.8</org.slf4j.version>
<log4j.version>1.2.16</log4j.version>
<xercesImpl.version>2.9.1</xercesImpl.version>
<org.springframework-version>3.1.2.RELEASE</org.springframework-version>
<tiles.core.api.servlet.jsp.version>2.2.2</tiles.core.api.servlet.jsp.version>
Related
Error:
java.lang.NoClassDefFoundError: org/springframework/data/geo/Metric
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.(JedisConnectionFactory.java:93)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at de.hybris.platform.spring.LazyInitOverrideBeanFactoryPostProcessor.forName(LazyInitOverrideBeanFactoryPostProcessor.java:82)
at java.base/java.util.Optional.map(Optional.java:265)
Even Jedis 3.x has the same issue.
Spring Dependencies:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.0</version>
</dependency>
Beans:
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="localhost"/>
<property name="port" value="6379"/>
</bean>
<bean id ="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<!-- redis template definition -->
<bean id="redisTemplate"
class="org.springframework.data.redis.core.RedisTemplate">
<property name="jedisConnFactory" ref="jedisConnFactory"/>
<property name="keySerializer" ref="stringRedisSerializer"/>
<property name="valueSerializer" ref="jdkSerializationRedisSerializer"/>
</bean>
I believe that to use Jedis 4.x you would need Spring 3.x. You need to drop to Jedis 3.x I believe. Although I don't believe the particular class you are getting a Class Not Found (Metric) which is Spring Data Commons has changed locations.
I just start working with an existing application where tests are mixed up (unit tests and integration tests) under src/test and i need to sort things out and put right tests at right place.
All are running fine with surefire right now but when trying to move integration test to failsafe, i can't figure out why it is not working.
I am getting this error while performing a select during a bean creation : java.lang.IllegalStateException: Failed to load ApplicationContext
It seems a table is missing in the database.
I can see that whith surefire, there is a step which uses hibernate to clear database and recreate it before running the tests but i can't see it with failsafe.
I don't know where to look up for this step and how to activate it with failsafe.
I am not very familiar with the environment but i know there is :
maven 3.2.5
maven-surefire-plugin 2.19.1
maven-failsafe-plugin 2.19.1
spring framework 4.0.0
Thanks for any suggestion for where to look.
Is there any difference between surefire and failsafe that need to be configured differently from one to another to run the exact same test?
The problem
Trying to create an MCVE, i figured out that the issue is not annotations but proguard-maven-plugin.
The problem can be reproduced with an sql database and a simple maven project with these files :
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>myGroupId</groupId>
<artifactId>myArtifactId</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>MCVE</name>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.5.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>5.1</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<executions>
<execution>
<phase>package</phase>
<goals><goal>proguard</goal></goals>
</execution>
</executions>
<configuration>
<proguardInclude>${basedir}/obfuscation.config.debug</proguardInclude>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>true</skip>
<includes>
<include>**/*It.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<skipTests>false</skipTests>
<includes>
<include>**/*It.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
User.java
package myPackage;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "users")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "username", nullable = false)
private String username;
public User() {}
public final String getUsername() {
return username;
}
public final void setUsername(final String pUsername) {
username = pUsername;
}
}
UserIt.java
package myPackage;
import org.junit.Test;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
#ContextConfiguration({"classpath:/test.xml"})
public class UserIt extends AbstractJUnit4SpringContextTests implements ApplicationContextAware {
#Test
public void myTest() {
System.out.println("MyTestIsOK");
}
}
obfuscation.config.debug
-dontshrink
-dontoptimize
-dontobfuscate
-dontpreverify
-ignorewarnings
-keep class **
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- xmlns:websocket="http://www.springframework.org/schema/websocket" -->
<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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"
>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://127.0.0.1:3306/test</value>
</property>
<property name="username">
<value>myUser</value>
</property>
<property name="password">
<value>myPwd</value>
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>myPackage</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<property name="generateDdl" value="true" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
</props>
</property>
</bean>
</beans>
Running clean integration-test with surefire will create the user table before running the test but not with failsafe.
It is hard to say something specific without having more information (e.g. relevant parts from pom.xml). Here are some general pointers to give some background though:
Maven build lifecycle
A normal Maven build runs through several phases. The relevant phases (with simplified descriptions) for this discussion are:
…
test: runs unit tests
…
(package: build a jar or war file)
pre-integration-test: prepares the environment for integration tests
integration-test: runs integration tests
post-integration-test: shuts down the integration test environment
verify: checks the result from the integration test
…
So Maven is designed to run integration tests in a special environment. An example would be that a Tomcat is set up and started and the projects war file (that was built in the package phase) is deployed on it in the pre-integration-test phase. Than the integration tests are run in the integration-test phase. In the post-integration-test phase the Tomcat is shut down. The test results are collected in the verify phase.
maven-surefire-plugin vs maven-failsafe-plugin
Both plugins belong to the Maven Surefire project.
The maven-surefire-plugin runs unit tests and binds to the test phase by default.
The maven-failsafe-plugin runs integration tests and binds to the integration-test and verify phases by default.
The reason that there are those two different plugins is, that the maven-failsafe-plugin does not fail the build immediately so the post-integration-test phase will run in any case. Only the verify phase fails the build on test failures.
Your problem
In response to your edits 1-3: Are you sure the integration tests include ContextManagerTest? It sounds like the maven-failsafe-plugin does not know about this test class and thus does not execute its #Before method and thus does not initialize the Spring context and thus does not recreate the database using Hibernate.
Try to create a MCVE by removing all irrelevant classes and configurations, only keeping e.g. one unit test, one integration test, the ContextManagerTest (each of which do something stupid like a System.out.println(…)) and the pom.xml.
I'm trying to log-in using Spring Security, my code has worked when I'm using jetty maven plugin. But now I want it to work when run on Jetty Embedded Server too. When I submit the log-in to spring security processing link, it show this warning:
HTTP ERROR: 500
INTERNAL_SERVER_ERROR
RequestURI=/auth/login_check
Caused by:
java.lang.AbstractMethodError
at javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
at javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:209)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:194)
at org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.applySessionFixation(ChangeSessionIdAuthenticationStrategy.java:48)
at org.springframework.security.web.authentication.session.AbstractSessionFixationProtectionStrategy.onAuthentication(AbstractSessionFixationProtectionStrategy.java:82)
at org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.onAuthentication(ChangeSessionIdAuthenticationStrategy.java:32)
at org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy.onAuthentication(CompositeSessionAuthenticationStrategy.java:83)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:216)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:534)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:879)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:741)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:213)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:403)
at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:522)
I'm guessing it conflict with jsp-2.1, jsp-api-2.1 jar of Jetty. What could I do to fix this? This is my jetty dependency:
<properties>
<jetty.version>6.1.14</jetty.version>
</properties>
...
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${jetty.version}</version>
</dependency>
<!--jsp support for jetty, add the 2 following -->
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-api-2.1</artifactId>
<version>${jetty.version}</version>
</dependency>
Spring security config in dispatcher servlet xml:
<security:http auto-config="true" use-expressions="true">
<security:form-login login-page="/login"
username-parameter="email" password-parameter="password"
login-processing-url="/auth/login_check" authentication-failure-url="/login?error"
default-target-url="/" always-use-default-target="true" />
<security:logout logout-url="/logout"
logout-success-url="/" delete-cookies="JSESSIONID" />
<security:remember-me token-validity-seconds="1209600"
remember-me-parameter="remember-me" data-source-ref="dataSource" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:password-encoder hash="md5" />
<security:jdbc-user-service
data-source-ref="dataSource"
users-by-username-query="select email, password, enabled from users where email=?"
authorities-by-username-query="select username, role from user_roles where username=?" />
</security:authentication-provider>
</security:authentication-manager>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/chamgroupdb" />
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="javax.persistence.validation.factory">validator</prop>
</props>
</property>
<property name="packagesToScan" value="com.chamgroup.model" />
</bean>
You need to upgrade Jetty for this to work.
javax.servlet.http.HttpServletRequest.changeSessionId() was introduced in Servlet 3.1.
Jetty 6 is Servlet 2.4 - and was EOL (End of Life) in 2010
Jetty 7 is Servlet 2.5 - and was EOL in 2014
Jetty 8 is Servlet 3.0 - and was EOL in 2014
Jetty 9.0 - 9.1 were releases based on early draft/alpha/beta releases of the Servlet 3.1 spec
Jetty 9.2.x was the first version to support the final Servlet 3.1 spec
Jetty 9.3.2 is the current stable version of Jetty (and requires Java 8)
I've read the other answers, but no matter,thanks
Spring:
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
</bean>
<bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="order" value="1" />
</bean>
pom.xml:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>2.0.13</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring3</artifactId>
<version>2.0.13</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
<scope>compile</scope>
</dependency>
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "login.html", template might not exist or might not be accessible by any of the configured Template Resolvers
Do you need a template resolver?
Try something like this:
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="templateMode" value="HTML5" />
</bean>
Make sure that /path/after/web-inf/login.html is being returned by a Spring MVC controller.
You are likely missing the "suffix" property within the templateResolver configuration. It should be best practice to use both a path "prefix" (where the file is located) and a "suffix" (the file extension - otherwise thymeleaf tries to resolve just "login" w/o an extension) within the template resolver configuration. Like so:
<beans:bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<beans:property name="prefix" value="/WEB-INF/views/"/>
<beans:property name="suffix" value=".html"/>
<beans:property name="templateMode" value="HTML5"/>
<beans:property name="cacheable" value="false"/> <!-- Development only -->
</beans:bean>
And requesting the login view within a controller does not include the file extension.
#RequestMapping(value = "/login")
public String login(HttpSession session) {
// do stuff
// Thymeleaf (delegated by springmvc) will request the "login" view at which
// point the prefix and suffix are added to resolve the template location.
return "login";
}
So based on this configuration and within a maven-based project, the login.html should be located at
${project_home}/src/main/webapp/WEB-INF/views/login.html
Maybe remove slash "/" in the controller request mapping will work.
#RequestMapping(value = "login")
In my case it turned out that thymeleaf html parser works poorly and doesn't accept one line html files. Formatting it solved the problem.
I am implementing generation of the domain/model POJOs from database using the Hibernate3 Maven Plugin. The rationale is to ensure a DBA's updates to the database are automatically mapped to the model layer before a developer starts working on further things. So the way it has to work is that a Hibernate CFG is generated and then POJOs; also since the older implementation consisted of developers using annotations instead of hbm.xml the generated classes are required to be annotated. Here's extract from the POM for Hibernate Maven Plugin
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>hibernate3-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>hbm2cfgxml</id>
<phase>generate-resources</phase>
<goals>
<goal>hbm2cfgxml</goal>
</goals>
<inherited>false</inherited>
<configuration>
<components>
<component>
<name>hbm2cfgxml</name>
<implementation>jdbcconfiguration</implementation>
</component>
</components>
<componentProperties>
<ejb3>true</ejb3>
<packagename>com.dss.domain</packagename>
</componentProperties>
</configuration>
</execution>
<execution>
<id>hbm2java</id>
<phase>generate-sources</phase>
<goals>
<goal>hbm2java</goal>
</goals>
<inherited>false</inherited>
<configuration>
<components>
<component>
<name>hbm2java</name>
<implementation>annotationconfiguration</implementation>
</component>
</components>
<componentProperties>
<ejb3>true</ejb3>
<packagename>com.dss.domain</packagename>
<configurationfile>target/hibernate3/generated-mappings/hibernate.cfg.xml</configurationfile>
</componentProperties>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.16</version>
</dependency>
</dependencies>
</plugin>
</plugins>
I can see the cfg.xml file is generated; but hbm2java fails with message
Failed to execute goal
org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2java (hbm2java) on
project dss-domain: Execution hbm2java of goal
org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2java failed: Unable
to load class declared as < mapping
class="com.dss.domain.Foo" / > in the configuration: -> [Help
1]
At a later stage all of this has to be moved the JPA implementation that we currently have, so the other question is do I then have to switch to jpaconfiguration in component properties?
Also none of these seems to work at all if I update the dependencies to the ones recently uopdated in the older project (Hibernate 3.6.6-FINAL); but that's a separate question posted here.
Any pointers or complete solutions are very welcome ;-)
I am using hibernate with mysql built with maven. Instead of running hbm2hbmxml I have changed my execution goals to only run hbm2cfgxml and hbm2java. Now my project generates annotation based pojos and hibernate.cfg.xml.
Hope this helps!
See my configuration:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springpress</groupId>
<artifactId>hibernate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hibernate</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.19</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.1.1.RELEASE</version>
<!-- will come with all needed Spring dependencies such as spring-core
and spring-beans -->
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.1.Final</version>
<!-- will come with Hibernate core -->
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>hibernate3-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>generate-xml-files</id>
<phase>generate-resources</phase>
<goals>
<!-- <goal>hbm2hbmxml</goal> -->
<goal>hbm2cfgxml</goal>
</goals>
</execution>
<execution>
<id>generate-entities</id>
<phase>generate-sources</phase>
<goals>
<goal>hbm2java</goal>
</goals>
</execution>
</executions>
<configuration>
<components>
<component>
<name>hbm2hbmxml</name>
<implementation>jdbcconfiguration</implementation>
<outputDirectory>target/classes</outputDirectory>
</component>
<component>
<name>hbm2cfgxml</name>
<implementation>jdbcconfiguration</implementation>
<outputDirectory>target/classes</outputDirectory>
</component>
<component>
<name>hbm2java</name>
<implementation>jdbcconfiguration</implementation>
<outputDirectory>target/generated-sources/hibernate</outputDirectory>
</component>
</components>
<componentProperties>
<propertyfile>src/main/resources/hibernate.properties</propertyfile>
<jdk5>true</jdk5>
<ejb3>true</ejb3>
<packagename>com.springpress.hibernate.entities</packagename>
<format>true</format>
<haltonerror>true</haltonerror>
</componentProperties>
</configuration>
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.19</version>
</dependency></dependencies>
</plugin>
</plugins>
</build>
</project>
And I have hibernate.properties like:
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/mydb
hibernate.connection.username=root
hibernate.connection.password=pass
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.default_schema=mydb
I was browsing through and saw a similar post (not sure how I missed it in the first place) but anyways, when I add an additional hbm2hbmxml to my build; the build does not fail in error
<execution>
<id>hbm2hbmxml</id>
<phase>generate-resources</phase>
<goals>
<goal>hbm2hbmxml</goal>
</goals>
<inherited>false</inherited>
<configuration>
<components>
<component>
<name>hbm2hbmxml</name>
<outputDirectory>target/classes</outputDirectory>
</component>
</components>
<componentProperties>
<packagename>com.sapient.dss.dbci.domain</packagename>
</componentProperties>
</configuration>
</execution>
But this is not the solution I am looking for. When I see hibernate.cfg.xml it is using mapping resources pointing to .hbm.xmls; and the generated java sources are using JPA annotations!!!
the hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/liquibrain</property>
<property name="hibernate.connection.username">liquibrain</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<mapping resource="com/dss/domain/Foo.hbm.xml" />
<mapping resource="com/dss/domain/Bar.hbm.xml" />
</session-factory>
</hibernate-configuration>
and here's an extract from the generated Java source:
/**
* Foo generated by hbm2java
*/
#Entity
#Table(name="iteration"
,catalog="liquibrain"
)
public class Foo implements java.io.Serializable {
...
...
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="id", nullable=false)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
...
...
...
#ManyToMany(fetch=FetchType.LAZY)
#JoinTable(name="bar_foos", joinColumns = {
#JoinColumn(name="foo_id", nullable=false, updatable=false) }, inverseJoinColumns = {
#JoinColumn(name="bar_id", nullable=false, updatable=false) })
public Set getBars() {
return this.bars;
}
Both the hbm files and java sources get packaged in the JAR, but since the hibernate.cfg.xml mentions mapping through .hbm.xml I belibe thats how it will be reffered. So isn't there a way to generate the java source without having to duplicate the info in form of both mappings and annotation configurations in POJOs? Makes me more confused about the plugin now than before.