Karaf 4.0.0 M2, Hibernate 4.3.6 и org.hibernate.PropertyAccessException

Я следую учебному пособию по Karaf/Database от Christian Schneider по следующему адресу: http://www.liquid-reality.de/display/liquid/2012/01/13/Apache+Karaf+Tutorial+Part+6+-+Database+Access

Мои изменения в этом руководстве должны использовать MySql и Hibernate вместо H2 и OpenJpa. С учетом вышесказанного я загружаю свой пользовательский пакет, но Hibernate не может использовать отражение для доступа к атрибутам в моем классе сущностей. Трассировка стека, которую я получаю, находится ниже.

У меня есть несколько конкретных вопросов:

  1. Нужен ли мне файл hibernate.properties, так как файл persistence.xml ссылается на источник данных и позволяет задавать свойства hibernate
  2. Есть ли в моем файле pom.xml дополнительные зависимости?
  3. Есть ли какая-либо другая причина, не связанная с pom.xml или hibernate.properties, которая вызывает исключение, показанное ниже?

Спасибо заранее за любые предложения. похотливый

2015-06-05 16:40:04,088 | ERROR | nsole user karaf | ShellUtil                        | 41 - org.apache.karaf.shell.core - 4.0.0.M2 | Exception caught while executing command
java.lang.reflect.UndeclaredThrowableException
    at com.sun.proxy.$Proxy72.persist(Unknown Source)[146:org.apache.aries.jpa.container.context:1.0.4]
    at net.lr.tutorial.karaf.db.examplejpa.impl.PersonServiceImpl.add(PersonServiceImpl.java:23)[167:leonard-orm-native:1.0.0]
    at Proxyead5dc4a_ed6c_46e9_8aad_e93af2278046.add(Unknown Source)[:]
    at net.lr.tutorial.karaf.db.examplejpa.command.AddPersonCommand.execute(AddPersonCommand.java:42)[167:leonard-orm-native:1.0.0]
    at org.apache.karaf.shell.commands.basic.AbstractCommand.execute(AbstractCommand.java:34)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.karaf.shell.compat.CommandTracker$1.execute(CommandTracker.java:109)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:67)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:87)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:480)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:406)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:182)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:119)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:94)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at org.apache.karaf.shell.impl.console.ConsoleSessionImpl.run(ConsoleSessionImpl.java:267)[41:org.apache.karaf.shell.core:4.0.0.M2]
    at java.lang.Thread.run(Thread.java:745)[:1.7.0_60-ea]
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_60-ea]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_60-ea]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_60-ea]
    at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_60-ea]
    at org.apache.aries.jpa.container.context.transaction.impl.JTAEntityManagerHandler.invoke(JTAEntityManagerHandler.java:185)[146:org.apache.aries.jpa.container.context:1.0.4]
    ... 16 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at com.sun.proxy.$Proxy76.persist(Unknown Source)
    ... 21 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_60-ea]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_60-ea]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_60-ea]
    at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_60-ea]
    at org.apache.aries.jpa.container.impl.EntityManagerProxyFactory$EMHandler.invoke(EntityManagerProxyFactory.java:31)
    ... 22 more
Caused by: javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of net.lr.tutorial.karaf.db.examplejpa.Person.name
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1187)
    ... 27 more
Caused by: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of net.lr.tutorial.karaf.db.examplejpa.Person.name
    at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:60)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:346)
    at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4746)
    at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4465)
    at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:243)
    at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:511)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:116)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
    ... 27 more
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field net.lr.tutorial.karaf.db.examplejpa.Person.name to net.lr.tutorial.karaf.db.examplejpa.Person
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)[:1.7.0_60-ea]
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)[:1.7.0_60-ea]
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)[:1.7.0_60-ea]
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)[:1.7.0_60-ea]
    at java.lang.reflect.Field.get(Field.java:379)[:1.7.0_60-ea]
    at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:57)
    ... 38 more

blueprint.xml

xsi:schemaLocation="
        http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0 
        http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance 
        http://aries.apache.org/xmlns/jpa/v1.0.0 http://aries.apache.org/xmlns/jpa/v1.0.0 
        http://aries.apache.org/xmlns/transactions/v1.0.0 http://aries.apache.org/xmlns/transactions/v1.0.0 ">

<bean id="personService" class="net.lr.tutorial.karaf.db.examplejpa.impl.PersonServiceImpl">
    <jpa:context unitname="Leonard" property="entityManager" />
    <tx:transaction method="*" value="Required" />
</bean>

<service ref="personService" interface="net.lr.tutorial.karaf.db.examplejpa.PersonService" />

<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
    <command name="person/add">
        <action class="net.lr.tutorial.karaf.db.examplejpa.command.AddPersonCommand">
            <property name="personService" ref="personService" />
        </action>
    </command>
    <command name="person/list">
        <action class="net.lr.tutorial.karaf.db.examplejpa.command.ListPersonsCommand">
            <property name="personService" ref="personService" />
        </action>
    </command>
    <command name="person/deleteAll">
        <action class="net.lr.tutorial.karaf.db.examplejpa.command.DeleteAllPersonsCommand">
            <property name="personService" ref="personService" />
        </action>
    </command>
</command-bundle>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="Leonard" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>osgi:service/Leonard</jta-data-source>
        <class>net.lr.tutorial.karaf.db.examplejpa.Person</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
        </properties>
    </persistence-unit>
</persistence>

Person.java

package net.lr.tutorial.karaf.db.examplejpa;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Person")
public class Person
{
    private String name;
    private String twitterName;

    public Person()
    {
    }

    public Person(String name, String twitterName)
    {
        super();
        this.name = name;
        this.twitterName = twitterName;
    }

    @Id
    @Column(name = "name", unique = true)
    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    @Column(name = "twitterName")
    public String getTwitterName()
    {
        return twitterName;
    }

    public void setTwitterName(String twitterName)
    {
        this.twitterName = twitterName;
    }
}

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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>info.leonard.orm</groupId>
    <artifactId>leonard-orm-native</artifactId>
    <version>1.0.0</version>
    <packaging>bundle</packaging>

    <properties>
        <log4j-version>1.2.16</log4j-version>
        <slf4j-version>1.6.1</slf4j-version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.apache.karaf.shell</groupId>
            <artifactId>org.apache.karaf.shell.console</artifactId>
            <version>4.0.0.M2</version>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>4.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.enterprise</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j-version}</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>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.6.Final</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-osgi</artifactId>
            <version>4.3.6.Final</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.6.Final</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate.common</groupId>
            <artifactId>hibernate-commons-annotations</artifactId>
            <version>4.0.4.Final</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j-version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.5.3</version>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        <Meta-Persistence>META-INF/persistence.xml</Meta-Persistence>
                        <Import-Package>
                            org.apache.felix.service.command;version="[0.6,1)",
                            org.apache.felix.gogo.commands;version="[0.6,1)",
                            org.apache.karaf.shell.console;version="[2.2,4)",
                            *,
                            org.hibernate.jpa,
                            org.hibernate.proxy,
                            javassist.util.proxy
                        </Import-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

PersonServiceImpl.java

package net.lr.tutorial.karaf.db.examplejpa.impl;

import java.util.List;
import javax.persistence.EntityManager;
import net.lr.tutorial.karaf.db.examplejpa.Person;
import net.lr.tutorial.karaf.db.examplejpa.PersonService;

public class PersonServiceImpl implements PersonService
{    
    private EntityManager em;

    public void setEntityManager(EntityManager em)    
    {
        this.em = em;
    }

    public void add(Person person)
    {
        em.persist(person);
        em.flush();
    }

    public void deleteAll()
    {
        em.createQuery("delete from Person").executeUpdate();
        em.flush();
    }

    public List<Person> getAll()
    {
        return em.createQuery("select p from Person p", Person.class).getResultList();
    }
}

Я перезапустил свой экземпляр karaf и просмотрел логи при запуске. Следующий пункт привлек мое внимание:

2015-06-06 04:17:02,988 | WARN  | FelixStartLevel  | aries                            | 144 - org.apache.aries.jpa.blueprint.aries - 1.0.4 | Managed persistence context support is no longer available for use with the Aries Blueprint container.

Обратите внимание, что мой пример использует управляемый контейнером JPA. Кажется странным, что это на самом деле не поддерживается, но в выходные попробую неуправляемую реализацию JPA.

1 ответ

Решение

Я развернул тот же код, что и в этом оригинальном посте, на экземпляр Apache Karaf 3.0.3, и код работает нормально. Проблема связана с Apache Karaf 4.0.0 M2, а точнее с Apache Aries v1.0.4.

Как сообщалось ранее, Aries 1.0.4 выдает следующее предупреждение при запуске в Karaf 4.0.0 M2

2015-06-06 04:17:02,988 | WARN  | FelixStartLevel  | aries                            | 144 - org.apache.aries.jpa.blueprint.aries - 1.0.4 | Managed persistence context support is no longer available for use with the Aries Blueprint container.

Это предупреждение указывает, что у Овна теперь есть проблема с объявлением артефактов в файле blueprint.xml.

Кристиан Шнайдер написал пост, показывающий, как Овен теперь использует аннотации для объявления контекста: http://www.liquid-reality.de/display/liquid/New+design+for+aries+jpa

Я еще не экспериментировал с этими аннотациями, но оставлю это другим, чтобы подтвердить, что Aries 1.0.4 (и, следовательно, Karaf 4.0.0) больше не поддерживает объявление контекста в файле blueprint.xml.

Другие вопросы по тегам