GWT-Objectify : basic - gwt

I've been through a few documentations, but am not able to communicate to the datastore yet...can anyone give me a sample project/code of objectify used in GWT web app(I use eclipse)...just a simple 'put' and 'get' action using RPC should do...or, atleast tell me how its done

Easiest way to understand how to make objectify work is to repeat all steps described in this article from David's Chandler blog. Whole blog is a pretty much must read if you interested in GWT, GAE(Java), gwt-presenter, gin\guice,etc. There you will find working example, but anyway here i'll show a slighly advanced example.
In package shared define your entity/model:
import javax.persistence.Embedded;
import javax.persistence.Id;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Unindexed;
#Entity
public class MyEntry implements IsSerializable {
// Objectify auto-generates Long IDs just like JDO / JPA
#Id private Long id;
#Unindexed private String text = "";
#Embedded private Time start;
// empty constructor for serialization
public MyEntry () {
}
public MyEntry (Time start, String text) {
super();
this.text = tText;
this.start = start;
}
/*constructors,getters,setters...*/
}
Time class (also shared package) contains just one field msecs:
#Entity
public class Time implements IsSerializable, Comparable<Time> {
protected int msecs = -1;
//rest of code like in MyEntry
}
Copy class ObjectifyDao from link above to your server.dao package. And then make DAO class specifically for MyEntry -- MyEntryDAO:
package com.myapp.server.dao;
import java.util.logging.Logger;
import com.googlecode.objectify.ObjectifyService;
import com.myapp.shared.MyEntryDao;
public class MyEntryDao extends ObjectifyDao<MyEntry>
{
private static final Logger LOG = Logger.getLogger(MyEntryDao.class.getName());
static
{
ObjectifyService.register(MyEntry.class);
}
public MyEntryDao()
{
super(MyEntry.class);
}
}
Finally we can make requests to database(server package):
public class FinallyDownloadingEntriesServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/plain");
//more code...
resp.setHeader("Content-Disposition", "attachment; filename=\""+"MyFileName"+".txt\";");
try {
MyEntryDao = new MyEntryDao();
/*query to get all MyEntries from datastore sorted by start Time*/
ArrayList<MyEntry> entries = (ArrayList<MyEntry>) dao.ofy().query(MyEntry.class).order("start.msecs").list();
PrintWriter out = resp.getWriter();
int i = 0;
for (MyEntry entry : entries) {
++i;
out.println(i);
out.println(entry.getStart() + entry.getText());
out.println();
}
} finally {
//catching exceptions
}
}

Related

Invalid lambda deserialization with Infinispan Cache and computeIfAbsent

I’m toying with an basic infinispan cluster and I came across a puzzling error.
I’m basically implementing a shared map, holding just one Integer
Here is the code of my service
package sandbox.infinispan.test.service;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.infinispan.Cache;
#Named("useThisOne")
#ApplicationScoped
public class CounterService implements ICounterService {
private static final String KEY = "key";
#Inject
private Cache<String, Integer> cache;
#Override
public void inc(final int amount) {
this.cache.put(KEY, Integer.valueOf(this.get() + amount));
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, k -> Integer.valueOf(0)).intValue();
}
}
Cache is produced with the following:
package sandbox.infinispan.test.config;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
#Dependent
class CacheProvider {
#Produces
#ApplicationScoped
private EmbeddedCacheManager defaultClusteredCacheManager() {
final GlobalConfiguration g = new GlobalConfigurationBuilder() //
.clusteredDefault() //
.transport() //
.nodeName(this.getNodeName()) //
.clusterName("infinispanTestCluster") //
.build();
final Configuration cfg = new ConfigurationBuilder() //
.clustering() //
.cacheMode(CacheMode.REPL_SYNC) ///
.build();
return new DefaultCacheManager(g, cfg);
}
}
When there are at least two servers in the cluster, computeIfAbsent fails with
15:48:50,253 ERROR [org.infinispan.interceptors.impl.InvocationContextInterceptor] (jgroups-7,myhostname-14393) ISPN000136: Error executing command ComputeIfAbsentCommand, writing keys [key]: org.infinispan.remoting.RemoteException: ISPN000217: Received exception from otherhostname-44445, see cause for remote stack trace
which drills down to:
Caused by: java.lang.NoSuchMethodException: sandbox.infinispan.test.service.CounterService.$deserializeLambda$(java.lang.invoke.SerializedLambda)
and finally to:
Caused by: java.lang.IllegalArgumentException: Invalid lambda deserialization
at sandbox.infinispan.test.service.CounterService.$deserializeLambda$(CounterService.java:10)
... 68 more
Caused by: an exception which occurred:
in object of type java.lang.invoke.SerializedLambda
If I rewrite my pretty nice fashionable code to the ugly following, it works.
#Override
public int get() {
Integer value = this.cache.get(KEY);
if (value == null) {
value = Integer.valueOf(0);
this.cache.put(KEY, value);
}
return value.intValue();
}
How can I use the pretty computeIfAbsent way of doing things nowadays ?
Eclipse 2018-12, WildFly 14, java 10 on of the dev member of the cluster, CentOs 7, OpenJdk 10, WildFly 14 on the remote cluster member.
Thanks for your help
Solved (kinda)
Thanks to the help I received here, I transformed the lambda into an inner class :
static class OhWell implements Serializable {
static Integer zero(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, OhWell::zero).intValue();
}
It works now, but it’s lots less nice than the neat lambda. So I’ll stick to the old-fashioned way – unless someone can think of a better way to do it.
Further results:
The following static inner class with a static method works
static class StaticOhWell implements Serializable {
static Integer apply(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, StaticOhWell::apply).intValue();
}
The following non static inner class with a non static method fails :
class NotStaticOhWell implements SerializableFunction<String, Integer> {
#Override
public Integer apply(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, new NotStaticOhWell()::apply).intValue();
}
It fails with this error message NotSerializableException: org.infinispan.cache.impl.EncoderCache:
13:41:29,221 ERROR [org.infinispan.interceptors.impl.InvocationContextInterceptor] (default task-1) ISPN000136: Error executing command ComputeIfAbsentCommand, writing keys [value]: org.infinispan.commons.marshall.NotSerializableException: org.infinispan.cache.impl.EncoderCache
Caused by: an exception which occurred:
in field sandbox.infinispan.test.service.CounterService.cache
in object sandbox.infinispan.test.service.CounterService#4612a6c3
in field sandbox.infinispan.test.service.CounterService$NotStaticOhWell.this$0
in object sandbox.infinispan.test.service.CounterService$NotStaticOhWell#4effd362
in field java.lang.invoke.SerializedLambda.capturedArgs
in object java.lang.invoke.SerializedLambda#e62f08a
in object sandbox.infinispan.test.service.CounterService$$Lambda$1195/1060417313#174a143b
Final words (?)
Using a “static lambda” (a static inner class implementing the SerializableFunction interface) worked too
static class StaticSerializableFunction implements SerializableFunction<String, Integer> {
#Override
public Integer apply(final String t) {
return Integer.valueOf(0);
}
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, new StaticSerializableFunction()::apply).intValue();
}
And the winner is…
Making the class actually serializable by “transienting” the Cache allows to simply use a method of this class. No need to create an inner class!
package sandbox.infinispan.test.service;
import java.io.Serializable;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.infinispan.Cache;
#Named("useThisOne")
#ApplicationScoped
public class CounterService implements ICounterService, Serializable {
private static final String KEY = "value";
#SuppressWarnings("cdi-ambiguous-dependency")
#Inject
private transient Cache<String, Integer> cache;
#Override
public void inc(final int amount) {
this.cache.put(KEY, Integer.valueOf(this.get() + amount));
}
#Override
public int get() {
return this.cache.computeIfAbsent(KEY, this::zero).intValue();
}
private Integer zero(#SuppressWarnings("unused") final String unused) {
return Integer.valueOf(0);
}
#Override
public void reset() {
this.cache.clear();
}
}
Thanks all!
According to Unable to deserialize lambda the deserializer needs the actual code to be available. Are you sure that your application is already started on all other nodes in the cluster (the exact same version, including your lambda)?
The computeIfAbsent() sends the lambda directly to the data (and therefore handles the operation using one RPC, instead of first fetching the value and then writing it as the 'ugly code'). In WF, your application lives in a different classloader (module) than Infinispan and that might cause an issue.
Could you try to refactor your lambda into a class and see if you get similar problem? I am not that knowledgeable about WF, so there might be a mitigation for regular classes that is missing for lambdas.

How can a static import be null

Since it's initialized in declaration, and the import implies by itself a dependency.
We have a jUnit parent test class like...
public class ServerTestBase extends TestBase {
public static final Client client = new Client();
...
And a Suite with the static import of the client and some init code in a #ClassRule using this client:
import static jwstest.test.ServerTestBase.client;
#RunWith(Suite.class)
#Suite.SuiteClasses({BunchOfSuites.class})
public class ScratchSuite {
#ClassRule
public static final ExternalResource testRule = new ExternalResource() {
#Override
protected void before() throws Throwable {
response = client.call(someService, HttpVerbs.GET).getResponse();
So, again, I don't understand, how in hell client can be null, since it's initialized on declaration, and the static import implies a dependency.
¿Any ideas? Thank you in advance.
The docs say that the field accessible in the #ClassRule has to be public static.
Static import is not such thing.
You can either extend ServerTestBase:
public class ScratchSuite extends ServerTestBase { ... }
... OR declare public static anew:
public static Client myClient = client; //from static import

How to add HTTP status code with error message in spring

I created one spring data jpa Application. In this application my method request is GET. but if I am trying to access that method Request url as post request. In this situation I want to know how to add HTTP status code 405(Method Not Allowed) with my custom error message.
Here is my code snippet
DepartmentModel
package com.demo.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "department")
public class DepartmentModel implements Serializable {
private static final long serialVersionUID = 1L;
#Id
public Integer ndeptid;
public String sdeptname ;
public Integer ninstid ;
public Boolean bislocked;
public String sclientdeptid;
public Integer nsurveymethodid;
public Boolean bisjointuse;
public Integer ntempdeptid;
public Boolean balternatejointusepercentage;
public Integer ndivid;
//getter and setter
DepartmentRepository
#Repository
public interface DepaertmentRepository extends JpaRepository<DepartmentModel, Integer>
{
#Query("select new map(dep.sdeptname as sdeptname)"
+ " from DepartmentModel as dep where dep.ninstid=60")
Set<DepartmentModel> findBySDepName();
}
DepartmentService
#Service
public class DepartmentService
{
#Autowired
DepaertmentRepository depRepo;
public Set<DepartmentModel> findDepName()
{
return depRepo.findBySDepName();
}
}
DepartmentController
#RestController
#RequestMapping("/SpaceStudy/SpaceAdmin")
public class DepartmentController {
#Autowired
DepartmentService depService;
#CrossOrigin(origins="*")
#GetMapping("AccountMaintenance/LoadDepartment")
//#ResponseStatus( value = HttpStatus.METHOD_NOT_ALLOWED)
public Set<DepartmentModel> findDepName() {
return depService.findDepName();
}
}
can any one help me how to add HTTP status code (405) with proper message when i am accessing GET request as post
You can override the method handleHttpRequestMethodNotSupported of ResponseEntityExceptionHandler and implement your own error message object. For example:
#Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest req) {
headers.setAllow(ex.getSupportedHttpMethods());
ErrorMessage errorMessage = ErrorMessage.of(
status.value(),
"You cannot make this request - the method is not allowed!",
ex.getMessage(),
((ServletWebRequest) req).getRequest().getServletPath()
);
return new ResponseEntity<>(errorMessage, headers, status);
}
#Value(staticConstructor = "of")
private static class ErrorMessage {
private Instant timestamp = Instant.now();
private Integer status;
private String error;
private String message;
private String path;
}
See my full demo for more info.
You can override not only this method of ResponseEntityExceptionHandler but all the remaining to get custom handling of other exceptions.
Note: you can use another approach to handle exceptions (or use both) - implement an exception handler.
UPDATE
It's necessary to add #ControllerAdvice annotation to the class that extended ResponseEntityExceptionHandler.

Returning JSON from RESTful Java server code?

I've inherited a web project that a contractor started. I and my coworkers are unfamiliar with the technology used, and have a number of questions. From what we can tell, this appears to be some sort of RESTful Java server code, but my understanding is there are lots of different types of Java RESTful services. Which one is this? Specific questions:
1) Where can we read more (particularly introductory information) about this specific service?
2) The code creates and returns a JSON through some kind of "magic"... I merely return a model class (code below) that has getter and setter methods for its fields, and it's automagically converted into a JSON. I'd like to learn more about how this is done automagically.
3) We already have some code that creates a JSON. We need to return this using this framework. If I already have a JSON, how do I return that? I tried something like this:
String testJSON = "{\"menu\": {\"id\": \"file\", \"value\": \"Hello there\"}}";
return testJSON;
instead of returning a model object with getters/setters, but this returns a literal text string, not a JSON. Is there a way to return an actual JSON that's already a JSON string, and have it be sent as a JSON?
You don't have to be able to answer all of the questions above. Any/all pointers in a helpful direction appreciated!
CODE
First, the view controller that returns the JSON:
package com.aimcloud.server;
import com.aimcloud.util.MySqlConnection;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.aimcloud.models.SubscriptionTierModel;
#Path("subscription_tier")
public class SubscriptionTierController
{
// this method will return a list of subscription_tier table entries that are currently active
#GET
#Produces({ MediaType.APPLICATION_JSON })
public String/*ArrayList<SubscriptionTierModel>*/ getSubscriptionTiers(#QueryParam("includeActiveOnly") Boolean includeActiveOnly)
{
MySqlConnection mysql = MySqlConnection.getConnection();
ArrayList<SubscriptionTierModel> subscriptionTierArray = new ArrayList<SubscriptionTierModel>();
String queryString;
if (includeActiveOnly)
queryString = "SELECT * FROM subscription_tier WHERE active=1";
else
queryString = "SELECT * FROM subscription_tier";
List<Map<String, Object>> resultList = mysql.query(queryString, null);
for (Map<String, Object> subscriptionRow : resultList)
subscriptionTierArray.add( new SubscriptionTierModel(subscriptionRow) );
// String testJSON = "{\"menu\": {\"id\": \"file\", \"value\": \"Hello there\"}}";
// return testJSON;
return subscriptionTierArray;
}
}
Next, the model the code above returns:
package com.aimcloud.models;
// NOTE this does NOT import Globals
import java.sql.Types;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
import com.aimcloud.util.LoggingUtils;
public class SubscriptionTierModel extends ModelPrototype
{
private String name;
private Integer num_studies;
private Integer cost_viewing;
private Integer cost_processing;
private Integer active;
protected void setupFields()
{
this.fields.add("name");
this.fields.add("num_studies");
this.fields.add("cost_viewing");
this.fields.add("cost_processing");
this.fields.add("active");
}
public SubscriptionTierModel()
{
super("subscription");
this.setupFields();
}
public SubscriptionTierModel(Map<String, Object> map)
{
super("subscription");
this.setupFields();
this.initFromMap(map);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setNum_Studies(Integer num_studies) {
this.num_studies = num_studies;
}
public Integer getNum_studies() {
return this.num_studies;
}
public void setCost_viewing(Integer cost_viewing) {
this.cost_viewing = cost_viewing;
}
public Integer getCost_viewing() {
return this.cost_viewing;
}
public void setCost_processing(Integer cost_processing) {
this.cost_processing = cost_processing;
}
public Integer getCost_processing() {
return this.cost_processing;
}
public void setActive(Integer active) {
this.active = active;
}
public Integer getActive() {
return this.active;
}
}
public abstract class ModelPrototype {
protected MySqlConnection mysql;
protected ArrayList<String> fields;
protected String table;
protected Integer id = null;
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
abstract protected void setupFields();
public ModelPrototype() {
mysql = MySqlConnection.getConnection();
this.fields = new ArrayList<String>();
this.fields.add("id");
}
public void initFromDbResult(List<Map<String, Object>> result) {
if (result.size() >= 1)
{
Map<String, Object> userRow = result.get(0);
this.initFromMap(userRow);
if (result.size() > 1)
{
Thread.dumpStack();
}
}
else
{
throw new WebApplicationException(ServerUtils.generateResponse(Response.Status.NOT_FOUND, "resource not found"));
}
}
protected void initFromMap(Map<String, Object> map) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object value = entry.getValue();
// LoggingUtils.log(entry.getKey() + " " + entry.getValue().toString());
if (value != null && this.fields.contains(entry.getKey())) {
this.setField(entry.getKey(), value);
}
}
}
....
1) Where can we read more (particularly introductory information)
about this specific service?
This is a RESTful service that uses basic jax-rs annotations to build the service. I suggest looking at a tutorial like "REST using jersey" or "REST using CXF".
2) The code creates and returns a JSON through some kind of "magic"...
The restful framework used usually takes care of this. #Produces({ MediaType.APPLICATION_JSON }) annotation indicates the framework to do this conversion.This will be defined somewhere in the configuration. Check the spring config files if you are using spring to define the beans. Usually a mapper or a provider will be defined that converts the object to json.
3) We already have some code that creates a JSON. We need to return this using this framework. If I already have a JSON, how do I return that? I tried something like this:
If you already have a json just return that json from the method. Remember to still have the #Produces({ MediaType.APPLICATION_JSON }) annotation on the method.
but this returns a literal text string, not a JSON
A json is a string. That is what you will see in the response, unless you deserialize it back to an object.
I suggest you read up on JAX-RS, the Java specification for RESTful web services. All of the "javax.ws.rs.*" classes/annotations come from JAX-RS
As JAX-RS, is just a specification, there needs to be something that implements the spec. There is probably a third-party, JAX-RS component that is used to run this service. Jersey in one popular implementation. Apache CXF is another.
Now back to JAX-RS. When you read up on this, you will see that the annotations on your class determine the REST characteristics of your service. For example,
#Path("subscription_tier")
defines your class as the resource with URI BASE_PATH/subscription_tier, where BASE_PATH is propbably defined in a configuration file for your web service framework.
As for how the objects are "automagically" converted into a JSON response: that is the role of the web service framework as well. It probably uses some kind of standard object-to-JSON mapping to accomplish this. (I have worked with CXF and XML resources. In that case JAXB was the mapping mechanism). This is a good thing, as the web service developer does not have to worry about this mapping, and can focus on coding just the implementation of service itself.

gwt rpc serialize generic class

I need to pass a class object through the gwt rpc connection as a generic but it seems that rpc does not cooperate with it. The class is serialized using the java.io.Serializable. I have checked it using the gwt IsSerializable but i still have the error.
Here is my code
MySource.java
#SuppressWarnings("serial")
#PersistenceCapable
#Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class MySource implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
#Persistent
private String userId;
#Persistent
private String title;
#Persistent
private String description;
#Persistent
private String blobKey;
#Persistent
private String youtubeLink;
#Persistent
private String personalLink;
#Persistent
private Date submitedDate;
#Persistent
private float price;
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getBlobKey() {
return blobKey;
}
public void setBlobKey(String blobKey) {
this.blobKey = blobKey;
}
public String getYoutubeLink() {
return youtubeLink;
}
public void setYoutubeLink(String youtubeLink) {
this.youtubeLink = youtubeLink;
}
public String getPersonalLink() {
return personalLink;
}
public void setPersonalLink(String personalLink) {
this.personalLink = personalLink;
}
public Date getSubmitedDate() {
return submitedDate;
}
public void setSubmitedDate(Date submitedDate) {
this.submitedDate = submitedDate;
}
public Long getId() {
return id;
}
}
AndroidSource.java
#SuppressWarnings("serial")
#PersistenceCapable
public class AndroidSource extends MySource{
public AndroidSource() {
super();
}
}
CategoryBrowseService.java which is the remoteservice model
#RemoteServiceRelativePath("categoryService")
public interface CategoryBrowseService extends RemoteService{
ArrayList<MySource> getSourceList(Class<? extends MySource> classType);
}
CategoryBrowseServiceAsync.java
public interface CategoryBrowseServiceAsync {
void getSourceList(Class<? extends MySource> classType,
AsyncCallback<ArrayList<MySource>> callback);
}
CategoryBrowsePresenter.java where the rpc is called
private void retrieveSources(Class<? extends MySource> classType) {
CategoryBrowseServiceAsync rpcService = GWT.create(CategoryBrowseService.class);
rpcService.getSourceList(classType, new AsyncCallback<ArrayList<MySource>>() {
#Override
public void onFailure(Throwable caught) {
Window.alert("Ooops!!!Sorry!Something went wrong.I am still beta!");
}
#Override
public void onSuccess(ArrayList<MySource> result) {
sourceList = result;
display.setSourceContent(sourceList);
}
});
}
CategoryBrowseServiceImpl.java
#SuppressWarnings("serial")
public class CategoryBrowseServiceImpl extends RemoteServiceServlet implements CategoryBrowseService{
private SourceDatastore dataStore;
public CategoryBrowseServiceImpl() {
dataStore = new SourceDatastore();
}
#Override
public ArrayList<MySource> getSourceList(Class<? extends MySource> classType) {
return dataStore.getSources(classType);
}
}
Here is the error that i get.
Compiling module com.sourcebay.SourceBay
Scanning for additional dependencies: file:/home/santaris/workspace/SourceBay/src/com/sourcebay/client/presenter/mybay/browse/CategoryBrowsePresenter.java
Computing all possible rebind results for 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService'
Rebinding com.sourcebay.client.model.mybay.browse.CategoryBrowseService
Invoking generator com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator
Generating client proxy for remote service interface 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService'
[ERROR] java.lang.Class<T> is not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' or 'java.io.Serializable' nor does it have a custom field serializer (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] java.lang.Class<T> has no available instantiable subtypes. (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] subtype java.lang.Class<T> is not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' or 'java.io.Serializable' nor does it have a custom field serializer (reached via java.lang.Class<? extends com.sourcebay.shared.source.MySource>)
[ERROR] Errors in 'file:/home/santaris/workspace/SourceBay/src/com/sourcebay/client/presenter/mybay/browse/CategoryBrowsePresenter.java'
[ERROR] Line 75: Failed to resolve 'com.sourcebay.client.model.mybay.browse.CategoryBrowseService' via deferred binding
The paradox is that when i am running my application through the eclipse plugin everything works fine. Could anyone help me please? I have checked to fix the problem through the DTO solution without any success. Moreover i have tried to implement a CustomFieldSerializer as Google suggests without any success too.
Thanks in advance,
Stefanos Antaris
P.S. Sorry for the huge post :-)
Well the problem is that you trying to transport a Class object over the network. I have no idea why it is working in dev mode (I've tried it on local project and it failed), but it shouldn't work. You have to use something else instead of Class name for example String, which will contain a name of class. Theoretically it can work if you create CustomFieldSerializer for Class, but using String instead of Class will be easier.
Classes with persistence annotations can work well on the server side, but if you want to pass its data to the client you must create a plain java serializable class to transport data from server to client.
As noted in the previous answer, persistence annotations are not supported in the client side, as they cannot be translated to equivalent javascript code (and it makes sense since the client doesn't have the responsability of persistence).
It could be that the persistence-related annotations in MySource.java make it implossible to translate to javascript. Try removing the annotations to see if it's related. Also make sure that MySource.java is in a package declared as translatable in the module xml file ("source" element).
Try using implements Serializable for defining you class.
I mean like this:
public class AndroidSource extends MySource implements Serializable{
public AndroidSource() {
super();
}
}
Your RPC Services must deal just with Serializable Objects. Domain classes are not translatable to JavaScript So GWT can't send and receive via network (RPC Protocole) such objects. You need to create DTO classes (wich shadows domain class) implementing java.io.Serializable and then reconfigure all your RPC Service to use in input DTOs and output DTOs. Good Luck for your project.