javaee / jersey

This is no longer the active Jersey repository. Please see the README.md
http://jersey.github.io
Other
2.86k stars 2.36k forks source link

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

Closed glassfishrobot closed 9 years ago

glassfishrobot 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]

glassfishrobot commented 10 years ago

Reported by HeinBloed

glassfishrobot commented 10 years ago

@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

glassfishrobot commented 10 years ago

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.

glassfishrobot commented 10 years ago

@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...

glassfishrobot commented 10 years ago

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?

glassfishrobot commented 10 years ago

@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!

glassfishrobot commented 10 years ago

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

glassfishrobot commented 10 years ago

@AdamLindenthal said: Attaching the sample from HeinBloed.

glassfishrobot commented 10 years ago

@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

glassfishrobot commented 9 years ago

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.

glassfishrobot commented 9 years ago

@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

glassfishrobot commented 9 years ago

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

glassfishrobot commented 10 years ago

File: DeclarativeLinkingDemo.war Attached By: @AdamLindenthal

glassfishrobot commented 10 years ago

File: DeclarativeLinkingDemo.zip Attached By: @AdamLindenthal

glassfishrobot commented 7 years ago

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

glassfishrobot commented 9 years ago

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