java - org - maven hibernate validator
Problemas para obtener Hibernate Core e Hibernate Annotations usando Apache Ivy(pero también está relacionado con Maven2). (2)
¡Es largo! ;-)
Hay una gran cantidad de texto copiado en esta pregunta que lo hace parecer complicado. Y, para ser sincero, ¡es mucha información! Sin embargo, para una persona con experiencia, puede ser innecesario y fácil pasarlo por alto.
En esencia, me pregunto por qué mi proyecto de prueba básico Hibernate Core + Hibernate Annotations no funciona. Sospecho que faltan dependencias, pero estoy usando Apache Ivy, que pensé que obtendría dependencias transitivas automáticamente del repositorio de Maven2 ibiblio, pero es evidente que faltan dependencias (ver título más abajo en la publicación sobre dependencias).
Mi proyecto de prueba
Tengo un pequeño proyecto de prueba:
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="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/webcookieschema</property>
<property name="connection.username">webcookieuser</property>
<property name="connection.password">tHePaSsWoRd</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
</session-factory>
</hibernate-configuration>
Test.java
public class Test {
public static void main(String[] args) {
UserDAO udao = new HibernateUserDAO();
User u = new User();
u.setName("somename");
udao.store(u);
}
}
HibernateUserDAO.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
public class HibernateUserDAO implements
UserDAO {
private SessionFactory sessionFactory;
public HibernateUserDAO() {
AnnotationConfiguration annotConf = new AnnotationConfiguration();
annotConf.addAnnotatedClass(User.class);
annotConf.configure();
// The line below generates the exception!
sessionFactory = annotConf.buildSessionFactory();
}
@Override
public void store(User user) {
Session session = sessionFactory.openSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
session.saveOrUpdate(user);
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
throw e;
} finally {
session.close();
}
}
}
log4j.properties
log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %m/n
log4j.rootLogger=INFO,Stdout
log4j.logger.org.apache.wicket=INFO
log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=INFO
log4j.logger.org.apache.wicket.version=INFO
log4j.logger.org.apache.wicket.RequestCycle=INFO
UserDAO.java
public interface UserDAO {
public void store(User user);
}
User.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
private String name;
public User() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
La excepción que obtengo cuando ejecuto el proyecto de prueba:
Exception in thread "main" java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter
at org.hibernate.bytecode.javassist.BytecodeProviderImpl.getProxyFactoryFactory(BytecodeProviderImpl.java:49)
at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactoryInternal(PojoEntityTuplizer.java:203)
at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:181)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:158)
at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:76)
at org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping.<init>(EntityEntityModeToTuplizerMapping.java:80)
at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:325)
at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:457)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:131)
at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:84)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:261)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1327)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
at HibernateUserDAO.<init>(HibernateUserDAO.java:15)
at Test.main(Test.java:3)
Caused by: java.lang.ClassNotFoundException:
javassist.util.proxy.MethodFilter
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
... 15 more
Si le faltan dependencias
Cuando obtengo una ClassCastException (se incluye arriba), pensé que sería una buena idea comprobar que tengo todas las dependencias.
Si descargo el archivo Hibernate Core y miro en el directorio / lib del archivo que obtengo:
kent@rat:~/dl-web/hibernate-distribution-3.3.1.GA$ tree lib/
lib/
|-- bytecode
| |-- cglib
| | `-- hibernate-cglib-repack-2.1_3.jar
| `-- javassist
| `-- javassist-3.4.GA.jar
|-- optional
| |-- c3p0
| | `-- c3p0-0.9.1.jar
| |-- ehcache
| | `-- ehcache-1.2.3.jar
| |-- jbosscache
| | `-- jboss-cache-1.4.1.GA.jar
| |-- jbosscache2
| | `-- jbosscache-core-2.1.1.GA.jar
| |-- oscache
| | `-- oscache-2.1.jar
| |-- proxool
| | `-- proxool-0.8.3.jar
| `-- swarmcache
| `-- swarmcache-1.0RC2.jar
`-- required
|-- antlr-2.7.6.jar
|-- commons-collections-3.1.jar
|-- dom4j-1.6.1.jar
|-- javassist-3.4.GA.jar
|-- jta-1.1.jar
`-- slf4j-api-1.5.2.jar
Si descargo las Anotaciones de Hibernate y hago lo mismo, obtengo lo siguiente:
kent@rat:~/dl-web/hibernate-annotations-3.4.0.GA$ tree lib/
lib/
|-- README.txt
|-- build
| |-- ant-contrib-1.0b2.jar
| |-- ant-junit-1.6.5.jar
| `-- junit-3.8.1.jar
|-- dom4j.jar
|-- ejb3-persistence.jar
|-- hibernate-commons-annotations.jar
|-- hibernate-core.jar
|-- slf4j-api.jar
`-- test
|-- antlr.jar
|-- asm-attrs.jar
|-- asm.jar
|-- commons-collections.jar
|-- javassist.jar
|-- jta.jar
|-- junit.jar
|-- log4j.jar
`-- slf4j-log4j12.jar
De manera predeterminada , creo que Ivy usa los servidores ibiblio en el modo Maven2 para recuperar sus dependencias . Estoy usando este ivy.xml para configurar las dependencias que deseo:
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<info
organisation="testorganization"
module="hibernatetest"
status="integration"/>
<configurations>
<conf name="runtime" description="" />
</configurations>
<dependencies>
<dependency org="mysql" name="mysql-connector-java" rev="5.1.6" conf="runtime->default"/>
<dependency org="org.hibernate" name="hibernate-core" rev="3.3.1.GA" conf="runtime->default"/>
<dependency org="org.hibernate" name="hibernate-annotations" rev="3.4.0.GA" conf="runtime->default">
<include></include>
</dependency>
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.5.6" conf="runtime->default"/>
</dependencies>
</ivy-module>
La dependencia JAR que realmente obtengo es:
kent@rat:~/.ivy2/cache$ ls -R1 * | egrep ''.jar$''
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
jta-1.1.jar
log4j-1.2.14.jar
mysql-connector-java-5.1.6.jar
ejb3-persistence-1.0.2.GA.jar
hibernate-annotations-3.4.0.GA.jar
hibernate-commons-annotations-3.1.0.GA.jar
hibernate-core-3.3.1.GA.jar
slf4j-api-1.5.6.jar
slf4j-log4j12-1.5.6.jar
xml-apis-1.0.b2.jar
En el archivo POM para hibernate-core en ibiblio hay algunas líneas que me pregunto:
<dependencies>
...
...
...
<!-- optional deps for bytecode providers until those are finally properly scoped -->
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.4.GA</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-cglib-repack</artifactId>
<version>2.1_3</version>
<optional>true</optional>
</dependency>
</dependencies>
¿Qué quieren decir? ¿Los necesito a ambos? ¿Por qué se configuran como opcionales si realmente se requieren siempre? ¿Y cómo los obtengo?
Especificaría explícitamente javassist en tu proyecto como una dependencia y vería si eso funciona.
En cuanto a por qué aparece como opcional, hay varias razones por las que alguien haría eso, pero en este caso, parece que el equipo de Hibernate no se ha decidido por el alcance real de la dependencia:
<!-- optional deps for bytecode providers until those are finally properly scoped -->
Tuve que agregar , opcional a mi Ivy.xml para obtener también la configuración opcional, que era necesaria para que todas las dependencias se recuperaran y para que el proyecto se ejecutara correctamente.
dependency org="org.hibernate" name="hibernate-core" rev="3.3.1.GA" conf="runtime->runtime,optional"/>