eclipse-ee4j / jersey

Eclipse Jersey Project - Read our Wiki:
https://github.com/eclipse-ee4j/jersey/wiki
Other
690 stars 353 forks source link

Declarative linking with mixed JAXB/JPA entities using EclipseLink leads to ValidationException #2897

Closed jerseyrobot closed 9 years ago

jerseyrobot commented 10 years ago

This issue must be due to the same reasons as https://java.net/jira/browse/JERSEY-2490, however in this specific situation, it is not only an improvement request but a bug.

I'm using mixed JAXB/JPA entities like this:

@Entity
@Table( name = "user", schema = "public" )
@Access( AccessType.PROPERTY )
@XmlAccessorType( XmlAccessType.PROPERTY )
@XmlRootElement
public class User implements Serializable
{
   private Integer dbid;
   private String login;
   private String password;
   private Integer version;
   private List<Role> roles;

   @Id
   @GeneratedValue( strategy = GenerationType.IDENTITY )
   @Column( name = "dbid" )
   public Integer getDbid()
   {
      return this.dbid;
   }

   public void setDbid( Integer dbid )
   {
      this.dbid = dbid;
   }

   @Column( name = "login", unique = true, nullable = false, length = 256 )
   public String getLogin()
   {
      return this.login;
   }

   public void setLogin( String login )
   {
      this.login = login;
   }

   [...]
}

If I just register the DeclarativeLinkingFeature, i.e. not even use any tt>@InjectLink</tt annotations, I run into this exception:

Exception [EclipseLink-7097] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Operation not supported: [iterator].
    at org.eclipse.persistence.exceptions.ValidationException.operationNotSupported(ValidationException.java:1493)
    at org.eclipse.persistence.internal.helper.linkedlist.ExposedNodeLinkedList.iterator(ExposedNodeLinkedList.java:67)
    at org.glassfish.jersey.linking.FieldProcessor.processLinks(FieldProcessor.java:145)
    at org.glassfish.jersey.linking.FieldProcessor.processMember(FieldProcessor.java:161)
    at org.glassfish.jersey.linking.FieldProcessor.processLinks(FieldProcessor.java:152)
    at org.glassfish.jersey.linking.FieldProcessor.processMember(FieldProcessor.java:161)
    at org.glassfish.jersey.linking.FieldProcessor.processLinks(FieldProcessor.java:152)
    at org.glassfish.jersey.linking.FieldProcessor.processMember(FieldProcessor.java:161)
    at org.glassfish.jersey.linking.FieldProcessor.processLinks(FieldProcessor.java:152)
    [...]

There is actually a huge sequence of FieldProcessor.processMember/processLink calls below that. By debugging, I found out that the processed HashSet in FieldProcessor grows to about 315,000 entries just before the ExposedNodeLinkedList is processed. I presume that that is due to JPA proxying the entity with all sorts of extra properties, all of which are then processed recursively. In fact, I found countless JPA-related objects in the processed HashSet on further inspection.

The real "culprit" is ExposedNodeLinkedList, which does not support iterator() (which gets called implicitly in FieldProcessor line 145: for (Object member : collection)), so this could be regarded as a problem of EclipseLink.

But the declarative linking feature is basically unusable in this situation. Needless to say that recursing through those 300k+ objects also takes quite some time.

Offering something like a tt>@NoLink</tt annotation, like suggested in the other issue, would not even help with this problem.

Affected Versions

[2.10.1]

jerseyrobot commented 6 years ago
jerseyrobot commented 10 years ago

@glassfishrobot Commented Reported by HeinBloed

jerseyrobot commented 10 years ago

@glassfishrobot Commented @AdamLindenthal said: Hi HeinBloed,

thank you for reporting an issue and thumbs up for taking your time to provide such detailed description. We appreciate this. However, this seems to be happening in a bit more complex environment - I did not succeed to reproduce this using small sample project based on your code and instructions.

It would be very helpful, if you could provide some bare-bone minimalistic (ideally maven-based) project, that would reproduce the failure, so that we have the entire context (incl. dependencies, etc).

For now, I am moving the issue to backlog.

Regards, Adam

jerseyrobot commented 10 years ago

@glassfishrobot Commented heinbloed said: Hi Adam,

thanks for your reply. I'm afraid I don't have a Maven project right now (we're really "old school" here ), but I'll try to assemble a complete list of files for a minimalistic demonstration project.

jerseyrobot commented 10 years ago

@glassfishrobot Commented @AdamLindenthal said: Thanks! Maven is not necessary, some zipfile with content, that is runnable (or deployable) somehow and demonstrates the problem you are facing is just fine.

Just to warn you - you don't have to hurry, the issue is not yet planned and unfortunately it may take some time...

jerseyrobot commented 10 years ago

@glassfishrobot Commented heinbloed said: Hi Adam,

I'd have a minimal project ready to share now, is there a preferred way to make it accessible to you? Otherwise I'd just upload the zip/war file to a free filehoster?

jerseyrobot commented 10 years ago

@glassfishrobot Commented @AdamLindenthal said: Hi HeinBloed,

unfortunately, our JIRA instance does not support file upload by users. So I leave this up to you - choose free file hosting or simply send it to me via email (adam.lindenthal at oracle.com). I will attach it here to the JIRA issue.

Thanks!

jerseyrobot commented 10 years ago

@glassfishrobot Commented heinbloed said: I've sent you an email with some deployment instructions - hope you can get it to work.

jerseyrobot commented 10 years ago

@glassfishrobot Commented @AdamLindenthal said: Attaching the sample from HeinBloed.

jerseyrobot commented 10 years ago

@glassfishrobot Commented @AdamLindenthal said: Hi,

thank you for the sample and for the further explanation. I will quote he the email from you, as someone else might investigate this issue:

I've attached two files. The WAR file should be deployable as is on a GlassFish 4.x instance, provided you have a running PostgreSQL database and defined a JDBC resource for that database in the GlassFish administration that is named "jdbc/demoResource".

I've been using GF nightly builds recently that include Jersey 2.10.1 (or even 2.10.4 now). The "com.acme.User" JPA entity is quite hackish; it uses the built-in PostgreSQL pseudo-table "user" so that you don't have to create an extra table for the test. If Postgres is not an option, just change the JDBC connection pool in GF accordingly and optionally adjust the User entity mapping.

After deploying, you should get the cited exception after a little time upon making an HTTP GET request to http://[host]:8080/DeclarativeLinkingDemo/users. If you unregister the DeclarativeLinkingFeature in "com.acme.DeclarativeLinkingDemoApplication", the current Postgres user (in my example) will just be returned without errors.

The ZIP file just contains my raw Eclipse project export with the sources and project setting files (sources also included in the WAR).

I hope you can make it run relatively easily now, feel free to ask for support if you think I can help with it.

Let me reiterate: the problem must be that the Declarative Linking feature recurses through all the properties found on a JAXB object to be marshalled. If that object is proxied by a mechanism like JPA, this number of properties is large and recursing through their whole hierarchy takes very long, and in the case of EclipseLink as the JPA provider eventually runs into an Exception.

Thanks, Adam

jerseyrobot commented 9 years ago

@glassfishrobot Commented gdavison said: Sorry about the problem you were seeing, I am looking into this now and it appears that for most JPA implementations that the extra field is labeled as being synthetic, so I am going to look at whether filtering those out solves the problem.

jerseyrobot commented 9 years ago

@glassfishrobot Commented @AdamLindenthal said: There is a pull-request from Gerard waiting for last few small steps before being merged.

https://github.com/jersey/jersey/pull/146

Regards, Adam

jerseyrobot commented 9 years ago

@glassfishrobot Commented @AdamLindenthal said: Pull request from gdavison was merged, closing the issue. Thanks for reporting.

jerseyrobot commented 10 years ago

@glassfishrobot Commented File: DeclarativeLinkingDemo.war Attached By: @AdamLindenthal

jerseyrobot commented 10 years ago

@glassfishrobot Commented File: DeclarativeLinkingDemo.zip Attached By: @AdamLindenthal

jerseyrobot commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA JERSEY-2625

jerseyrobot commented 9 years ago

@glassfishrobot Commented Marked as fixed on Monday, March 2nd 2015, 11:52:11 am