views:

313

answers:

2

I'm not really sure how annotations actually work. I'm using JAXB and JPA (with eclipselink) on the same classes, i. e. I get class definitions like this:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Channel")
@Entity
public class Channel extends NamedEntity {
    @XmlAttribute
    @XmlSchemaType(name = "anyURI")
    @Column(name="url")
    protected String url;

    @XmlAttribute
    @Column
    protected String coDirection;
    // etc...
}

Now I'm getting weird errors (for example "com.econemon.suite.common.models.Channel@115c974 is not a known entity type" which would usually mean that the class is not in my persistence.xml) and I'm wondering whether the annotations will interfere with each other?

A: 

No, they don't.

I removed all other annotations and cut the inheritance and ended up with a very simple class. Problem remained.

A thing that wasn't mentioned in my post (because I thought it wasn't relevant) was that I'm running this inside an OSGi container (Felix if that matters). Now, such a container shields different "bundles" from each other, so they can't see each other's classes until you specifically "export" packages.

The annotated classes were sitting in a different bundle than my persistence.xml and I assumed that I could just import the annotated classes from another bundle and do the persistency init stuff elsewhere. Turns out I can't, although I haven't really understood why.

So, if you're using JPA in conjunction with OSGi bundles, you have to make sure that:

  • Annotated classes and persistence.xml are together in the same bundle
  • this bundle exports the package containing the annotated classes
  • the persistency unit(s) are listed in the bundle's manifest file

You can then do the actual persistency things (like calling EntityManager.persist) in different bundles.

As a side note, I got similarly weird errors when trying to use JAXB annotations across bundles. It seems that the JAXBContext and / or the ObjectFactory have to be instantiated in the same bundle that contains the annotated classes. I couldn't really nail this down, but putting things in the same bundle helped.

It would be great if someone with a deeper understanding of OSGi, class loading and annotations could comment on what might be happening here.

Update: exporting / importing the proper annotation packages might enable you to have persistence.xml and annotated classes in different bundles, see here. Haven't tested, though.

Hanno Fietz
+2  A: 

Hello,

An annotation can't interfere an other annotation, esp. not if the came from different packages and have different names. Each framework (JAXB and Hibernate) have there own annotations. Each framework introspect only there own annotations. I'm very sure that this is not the problem here.

please check your entity to have this:

a) no argument constructor (default constructor is fine, but if you have only constructors with arguments, you must provide a no argument constructor to JPA, this can be protected or package visible....)

b) an @Id Annotation on a field or getter (we always use field based annotations, otherwise never mix JPA getter annotation with field annotation in a type!)

c) the type is in your persistence unit and your persistence unit is used

d) the type has a @Entity Annotation

if you use inheritance (extends NamedEntity), you have to give more JPA more information how you what to map this. At first try to remove the extends NamedEntity stuff. And than look at a good JPA Tutorial which explains the inheritance variants.

KlausMeier
+1 for the checklist, this is generally quite useful. However, I had already worked through it before I posted. I finally figured it to be some class loading problem that I still don't really understand, but was able to solve / work around anyway. Also see my own answer.
Hanno Fietz