开发者

GWT Deserialisation of Persistent Entities (JPA)

I am currently developing Java/GWT-application which is hosted on a weblogic application server. I am using EJB3.0 with EclipseLink as persistence layer. Sadly my GWT has problems to deserialize persistent entities.

It might be helpful for you to know, that I

  • have the EclipseLink-Library in my classpath (including javax.persistence.Entity)
  • am not recieving the persistence objects from a database or persistence-manager - I am creating the objects with standard java code
  • use Eclipse IDE for Java EE Developers for development and deploying and I am compiling my GWT code with the GWT-Plugin (GWT 2.1.0) - my source code is split up in several projects
  • am pretty sure, that the problems occures on client side, since the HTTP response of my server is the same in my working and in my not working example
  • tried to patch javax.persistence.Entity and tried to include several libraries which included javax.persistence.Entity but nothing was helping
  • a minimal project with just this code works fine, but this code integrated in our project environment does not work

UPDATE: it looks like this whole topic is some problem with rpc.enhancedClasses. I added the interesting contents of my generated .gwt.rpc-files. It seems to be unnormal, that the data transfered over HTTP is the same, although these .rpc files differ. These links might be interesting: RemoteService.gwt.xml and the documentation for enhances classes

In my server provides a list of instances of class SerialClass; the interface looks like this:

public interface GreetingService extends RemoteService {
    List<SerialClass> greetServer();
}

My onModuleLoad()-Method gets those instances and creates a browser-popup with the information:

public void onModuleLoad() {
    GreetingServiceAsync server = (GreetingServiceAsync) GWT.create(GreetingService.class);
    server.greetServer(new AsyncCallback<List<SerialClass>>() {
        public void onFailure(Throwable caught) {
        }

        public void onSuccess(List<SerialClass> result) {

            String resultString = "";
            try {
                for (SerialClass serial : result) {
                    if (serial == null) {
                        resultString += "null ";
                    } else {
                        resultString += ">" + serial.id + "< ";
                    }
                }
            } catch (Throwable t) {
                Window.alert("failed to process");
            }

            Window.alert("success:" + resultString);
        }
    });

}

My server is looking like this:

public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
    public List<SerialClass> greetServer() throws IllegalArgumentException {
        List<SerialClass> list = new ArrayList<SerialClass>();
        for (int i = 0; i < 100; i++) {
            list.add(new SerialClass());
        }
        return list;
    }
}

Case 1 => everything works fine

I am using this SerialClass (either without any annotation, or with any annotation other than Entity - for example javax.persistence.PersistenceContext works fine):

//@Entity
public class SerialClass implements Serializable, IsSerializable {
    public int id = 4711;
}

The popup contains (as expected):

success:>4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711< >4711<

The data sent over HTTP looks like this:

//OK[4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,100,1,["java.util.ArrayList/3821976829","serial.shared.SerialClass/10650133"],0,6]

The generated .xml.rpc-file (4F138A4EA095EA4C468507AF3CA19D8F.gwt.rpc) contains:

my.package.SerialClass, true, true, false, false, my.package.SerialClass/2805025871, 2805025871
[Lmy.package.SerialClass;, true, true, false, false, [Lmy.package.SerialClass;/600614154, 600614154

Case 2 => its not working at all

I am using this SerialClass:

@Entity
public class SerialClass implements Serializable, IsSerializable {
    public int id = 4711;
}

My popup contains (THIS IS MY PROBLEM):

success:>2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null >2< null 

The data sent over HTTP looks like this (exactly the same!):

//OK[4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,4711,2,100,1,["java.util.ArrayList/3821976829","serial.shared.SerialClass/10650133"],0,6]

The generated .xml.rpc-file (E81A9E44448F41D2EC63CD508632C10B.gwt.rpc) contains:

my.package.SerialClass, true, true, false, false, my.package.SerialClass/2805025871, 2805025871
@ClientFields,my.package.SerialClass,id
[Lmy.package.SerialClass;, true, true, false, false, [Lmy.package.SerialClass;/600614154, 600614154

There is no suspicious logging output - neither on server, nor on client. All HTTP-responses have return code 200.

My current workaround

I am going to try to create transfer objects开发者_运维问答 as a copy of my SerialClass - those transfer objects will look exactly the same, but will not have the @Entity annotation.

Alternatively I could try to use the RequestFactory (thanks to @Hilbrand for the hint).

I really don't know how to solve that problem and I'm really thankful about any suggestions, hints, tips, links, etc.


With GWT RPC you can't serialize any class that contains code that can't be compiled to JavaScript and as you suggest the way to go forward is creating transfer objects.

An alternative is to use the GWT 2.1 RequestFactory, see also this article http://blog.ltgt.net/gwt-211-requestfactory. But it's a different both on client/server side than RPC so you need to refactor the client/server side implementation, which could cost more time than writing transfer objects.


I have mentioned how to use JPA 2.0 entities at GWT layer at my blog. And also, I have a created a eclipse project to simulate your scenario. You can download it by using this link . I have used GWT 2.2, if your gwt version is below 2.1 , then you should also add gwt-java-math to your project.


Ok, we found a solution! Thanks for everyone that helped me!

GWT was unable to serialize the objects of my annotated class, because the .gwt.rpc-files were not accessible via servlet context.

The solution was to create just one war file containing all javascript, html and rpc resources. This war file now also contains the servlet definitions (in the web.xml). Our java code is deployed in seperate modules (jar files), which are referenced by that war file.


A work-a-round:

You need to provide sources of used annotations to be compiled by GWT compiler.

Just create special source directory, which will be used for GWT-compilation only, and copy there the sources of annotations.


There is no need to create copies of your value-objects. I encountered such problem before. I've uploaded a application skeleton to help you get started(minus libraries). Let me know if you cannot use SVN.


The way I had handled this was by creating DTO's or value objects. GWT requires source files on the client side. I Don't think there is any way around it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜