RequestFactory ValueProxy class with embedded List of another ValueProxy not visible in response on client - gwt

I have a requestfactory service request that returns a List<> of RoleProxy. The RoleProxy contains a List<> of PermissionProxy. I can see the data coming back from the server. I can see it in the data that is being parsed by the AutoBean decode. But the response RoleProxy in the onSuccess method does not have any data in it's List<>.
Here is the RoleProxy
#ProxyForName("com.ihg.atp.schema.crs.revenue.sbrpa.datatypes.v1.RolesType")
public interface RoleProxy extends ValueProxy {
public int getId();
public void setId(final int id);
public String getName();
public void setName(final String name);
public List<PermissionProxy> getPermissions();
public void setPermissions(final List<PermissionProxy> permissions);
}
The Permissions Proxy
#ProxyForName("com.ihg.atp.schema.crs.revenue.sbrpa.datatypes.v1.PageType")
public interface PermissionProxy extends ValueProxy {
public String getPageIndex();
public void setPageIndex(final String pageIndex);
public String getAccessType();
public void setAccessType(final String accessType);
}
And the calling routine
RolesContext ctx = requestFactory.rolesContext();
ctx.getAllRoles().with("permissions").fire(new Receiver<List<RoleProxy>>() {
#Override
public void onSuccess(List<RoleProxy> response) {
#SuppressWarnings("unused")
List<PermissionProxy> perms = response.get(0).getPermissions();
// Here perms is an empty list instead of the data that was sent
}
});
Does anyone have an idea of what is happening here? I have done similar things in the past with EntityProxies.
On Edit: Added link to response body.

Related

How to use set , get in gwt shared folder

I have a class select in gwt shared folder with some set and get function like..
public class Select implements Serializable {
private static final long serialVersionUID = 1L;
String userid=null;
String name=null;
/******************Set********************/
public void setId(String userid) {
this.userid=userid;
}
public void setName(String name) {
this.name=name;
}
/******************get*************************/
public String getId() {
return userid;
}
public String getName() {
return name;
}
now I called setid() and getid() from server,its working . but when i am calling getid() from client, its returning me a null value please some one help me ...
my client side code is ...
greetingService.select(new AsyncCallback<String>()
{
Select sel=new Select();
public void onSuccess(String result) {
System.out.println("client..id"+sel.getId());
});
sel.getid() is returning null because its not being set by anything. You are simply calling new Select() and creating a new Select object on the client. If you want to retrieve the Select object with data in it form the server you need to pass it as the result parameter of the AsyncCallback callback via an RPC service, like so:
greetingService.select(new AsyncCallback<Select>() {
public void onSuccess(Select result) {
// Do what you want with the Select object returned via server
}
public void onFailure(Throwable caught) {
System.out.println("Call failed " + caught.getMessage());
}
});
Assuming you have set up the RPC service properly, you will handle the server end as a regular method:
public class GreetingServiceImpl extends RemoteServiceServletImpl {
public Select select() {
Select select = new Select();
select.setId(1);
return select;
}
}
You may find this tutorial helpful http://www.gwtproject.org/doc/latest/tutorial/RPC.html

POJO information lost during RPC call (GWT)

I am having issues with RPC calls and GWT. Essentially, I have a Person class (common code between client and server) that is created in the client side web code, sent to the server code via an RPC call, and then saved to a DB (OrientDB). I have verified that the following work:
RPC call - I am able to send info to the server and retrieve info from the server
save to DB - have verified that a Person object is saved to the DB
Where I am having issues is the transfer of the POJO from the client to the server. I have verified that the POJO's properties are intact right before it is sent to the server, however, the object passed to the server contains null values for all properties. Essentially, the class is transferred but the information is not. It then saves to the DB, but obviously without any relevant information contained within it.
I will copy what I feel is relevant below, please let me know what else I can provide to make this problem easier to identify. Note these are still in a testing state, so mind the comments :)
Any idea why my POJO's information is being lost in translation?
Person object, followed by the abstract class it inherits from:
public class Person extends org.matesweb.shared.AbsPerson implements Serializable
{
#Id
private String id; // DON'T CREATE GETTER/SETTER FOR IT TO PREVENT THE CHANGING BY THE USER APPLICATION,
// UNLESS IT'S NEEDED
//sets new user details
public void setPerson(String fIrstName, String mIdInit, String lAstName, String email, String password)
{
firstName = fIrstName;
middleInitial = mIdInit;
lastName = lAstName;
}
/*getter and setter methods - required for every
* field due to restrictions imposed by OrientDB*/
public Object getId()
{
String tmp;
tmp = id.toString();
return tmp;
}
//end class
}
public class AbsPerson implements Serializable
{
String firstName;
String middleInitial;
String lastName;
// public sys.Login login;
public org.matesweb.shared.Group[] groups;
private org.matesweb.shared.Purchase[] purchases;
/*this method adds a new purchase to the purchases variable*/
/* public void addPurchase(float price, String description)
{
people.Purchase newPurchase = new people.Purchase(login, price, description);
}
*/
/*adds a person to a group by comparing the passed in group ID and PWD*/
public void addGroup(String groupID, String groupPWD)
{
//compare group ID with group PWD to add a user to the group
}
/*getter and setter methods - required for every
* field due to restrictions imposed by OrientDB*/
public String getFirstName()
{
return firstName;
}
public void setFirstName(String name)
{
firstName = name;
}
public String getMiddleInitial()
{
return middleInitial;
}
public void setMiddleInitial(String midInit)
{
middleInitial = midInit;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String ln)
{
lastName = ln;
}
/*
public sys.Login getLogin()
{
return login;
}
public void setLogin(sys.Login log)
{
login = log;
}
*/
public org.matesweb.shared.Group[] getGroups()
{
return groups;
}
public void setGroups(org.matesweb.shared.Group[] gro)
{
groups = gro;
}
public org.matesweb.shared.Purchase[] getPurchases()
{
return purchases;
}
public void setPurchases(org.matesweb.shared.Purchase[] purch)
{
purchases = purch;
}
}
Service
package org.matesweb.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import org.matesweb.shared.Person;
#RemoteServiceRelativePath("peopleService")
public interface PeopleService extends RemoteService {
//test services
String stringTest(String outgoingString);
Person getPerson(String persId);
//production services
String savePerson(Person p);
}
ServiceAsync
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.matesweb.shared.Person;
public interface PeopleServiceAsync
{
//tests
void stringTest(String outgoingString, AsyncCallback<String> incomingString);
void getPerson(String persId, AsyncCallback<Person> retPerson);
//production services
void savePerson(Person p , AsyncCallback<String> st);
}
ServiceImpl call for this particular method:
//production calls
#Override
public String savePerson(Person p) {
String st = ioObj.saveObj(p);
if(st.equals("Success")){
return "Your information has been saved successfully!";
} else{
return "Something has gone wrong on our end... Sorry! Error:<br /> " + st;
}
}
and finally, the call itself
private static void savePerson(Person p)
{
// Initialize the service proxy.
if (peopleSvc == null) {
peopleSvc = GWT.create(PeopleService.class);
}
//resets status
st="";
// Set up the callback object.
AsyncCallback<String> callback = new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
st = caught.getMessage();
Label stLabel= new Label(st);
personTable.setWidget(3,1,stLabel);
}
#Override
public void onSuccess(String result) {
st = result;
HTML stLabel= new HTML(st);
joinPanel.add(stLabel);
}
};
// Make the call to the people service.
peopleSvc.savePerson(p, callback);
}
I was able to fix this issue by implementing GWT's IsSerializable interface. I also removed the Serializable interface from the Person class and let it inherit IsSerializable from the abstract class it inherits from.

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.

How to implement Rest web service using spring 3?

I have a Library application which is already implemented in spring MVC.
I need to use ReST web services for the same application using spring 3.
I have a Controller class I want is to be as a RestFul webService
#Controller #SessionAttributes("category")
public class CategoryController {
private static final Log log = LogFactory.getLog(CategoryController.class);
#Autowired
private CategoryService categoryService;
#Autowired
private ItemService itemService;
#RequestMapping("/category/categoryList.htm")
public ModelAndView list(HttpServletRequest request,
HttpServletResponse response) throws Exception {
List<Category> list = categoryService.getAllMainCategories();
Map map = new HashMap();
map.put("categoryList", list);
map.put("category", new Category());
return new ModelAndView("categoryList", map);
}
#RequestMapping(method = RequestMethod.POST, value = "/category/save.htm")
public String save(HttpServletRequest request,
HttpServletResponse response, Category command) throws Exception {
log.debug("save method called" + command);
Category category = (Category) command;
System.out.println(category);
categoryService.saveCategory(category);
return "redirect:/category/categoryList.htm";
}
#RequestMapping("/category/edit.htm")
public String edit(#RequestParam String id, ModelMap model)
throws Exception {
log.debug("edit method called :" + id);
log.debug(Long.parseLong(id));
Category cat = categoryService.getCategory(Long.parseLong(id));
model.put("categoryList", categoryService.getAllMainCategories());
model.put("category", cat);
return "categoryList";
}
#RequestMapping("/category/delete.htm")
public String remove(#RequestParam String id, ModelMap model)
throws Exception {
log.debug("remove method called " + id);
categoryService.deleteCategory(Long.parseLong(id));
return "redirect:/category/categoryList.htm";
}
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Category.class,
new PropertyEditorSupport() {
#Override
public void setAsText(String text) {
setValue(categoryService.getCategory(Long.valueOf(text)));
}
});
}
}
it is CategoryController class which add delete or update a category
ItemService and CategoryService are data sources
Category is a domain object having properties like id,name,description etc..,
How do I write a REST web service for this?
There's a simple example showing how in Barebones Spring. Check it out.

creating a GWT ValueProxy and sending to a service method

I want to call a method on a Service with a ValueProxy param - if I do personProxy.setName("test") and then request.callFn(personProxy).fire(), the name property doesn't get passed to server.
Should I do a request.edit(personProxy) before setting the name or something else?
This is the implementation I'm using:
//somewhere in MyActivity.java ...
PersonProxy cp = requestFactory.myRequest().create(PersonProxy.class);
cp.setName("John Doe");
requestFactory.myRequest().doSomething(cp,"extra_param_value").fire(new Receiver<List<PersonProxy>>() {
#Override
public void onSuccess(List<PersonProxy> response) {
//response from server...
}
});
//------------------------
public interface MyRequestFactory extends RequestFactory {
MyRequest myRequest();
}
//------------------------
#ServiceName(value="com.server.MyService", locator="com.server.MyServiceLocator")
public interface MyRequest extends RequestContext {
public Request<Integer> doSomething(PersonProxy param, String extraParam);
}
//------------------------
public class MyServiceLocator implements ServiceLocator {
public Object getInstance(Class<?> clazz) {
return new MyService();
}
}
//------------------------
public class MyService {
public Integer doSomething(Person param, String extraParam) {
System.out.println("person.name="+param.getName()); ---> prints NULL!!! why?
return 0;
}
}
//------------------------
#ProxyForName(value="com.server.Person")
public interface PersonProxy extends ValueProxy {
String getName();
void setName(String name);
}
//-----------------------
public class Person {
public Person() {
super();
}
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Thanks.
The PersonProxy is being created by one instance of a RequestContext and used in another. Turns out there's a bug in AbstractRequestContext.retainArg() that should have thrown an exception to tell you about the API mis-use. Editable proxies aren't supposed to be usable between different RequestContext instances.
TreeRequest ctx = factory.treeRequest();
PersonProxy person = ctx.create(PersonProxy.class);
person.setName("John Doe");
ctx.doSomething(person, "more stuff");
As discussed on IRC, the -Dgwt.rpc.dumpPayload=true JVM flag can be turned on when trying to diagnose where data is going (or isn't).