client parameters in GWT RequestFactory - gwt

I´m using GWT RequestFactory and want to transport client-side parameters in a service.
The parameters should be created on the client, because they aren´t part of the domain model and won´t be stored in the database.
Unfortunately I found no way to do this, because only xxxProxy objects can be used as parameters and they can only be created on the server.
My concrete example:
I want to download tasks from a server and want to send a filter object with the request as parameter, which specifies the task objects to be loaded.
Thanks for your help!

You can very-well create proxies on the client, using the create() method of your RequestContext. In your case, your proxy would have to be ValueProxy rather than an EntityProxy. You don't have to "store" value proxies (contrary to entity proxies).
I do have the exact same use case as yours, and it works very well.
#Service(MyService.class)
interface MyRequestContext extends RequestContext {
Request<List<TaskProxy>> findTasks(FilterProxy filter);
}
#ProxyFor(Filter.class)
interface FilterProxy extends ValueProxy {
// your getters and setters here
}
...
MyRequestContext ctx = ...;
FilterProxy filter = ctx.create(FilterProxy.class);
filter.setXxx(...);
// set your other filter
ctx.findTasks(filter).fire(new Receiver<List<TaskProxy>>() {
#Override
public void onSuccess(List<TaskProxy> tasks) {
// ...
}
});
As a side note, you wrote “only xxxProxy objects can be used as parameters”, which is wrong; you can very well use primitive types (int, boolean, etc.), their wrapper types (Integer, Boolean, etc.), String, Date, and List or Set of them (or proxy types).

Related

How should I relate Service Fabric Actors together?

I have a number of Actors which represent a single physical object (a IoT device).
On reviewing our code base we sometimes pass in an existing ActorReference into other Actors and other times we create a new proxy object.
I would have assumed that passing in a existing Actor Reference is more performant but I'm worried about side-effects so creating a new proxy object would seem lower risk.
What are the pro's and con's of each approach and what should I consider when making a decision on which approach to use ?
From researching a decompiled source code it seems to me using ActorReference.Bind and ActorProxy.Create is nearly equal:
public object Bind(Type actorInterfaceType)
{
return ActorProxy.DefaultProxyFactory.CreateActorProxy(actorInterfaceType, this.ServiceUri, this.ActorId, this.ListenerName);
}
public static TActorInterface Create<TActorInterface>(ActorId actorId, string applicationName = null, string serviceName = null, string listenerName = null) where TActorInterface : IActor
{
return ActorProxy.DefaultProxyFactory.CreateActorProxy<TActorInterface>(actorId, applicationName, serviceName, listenerName);
}
So there are no differences neither in reliability nor in performance.
ActorReference supports serialization so it seems more suitable for passing between actors.
Passing ActorReference is better and recommended approach as it allows you to create the ActorProxy with a custom ActorProxyFactory on the receiving side. If an actor is passed as an interface the de-serialization process uses the default actor proxy factory to bind the reference to the proxy and provide the proxy object to the receiving method.

JAX-RS consuming a custom object list inside a custom object

What is the way to consume a list of custom objects inside another custom object in JAX-RS CXF implementation? As an example my object looks like below
#POST
#Produces({MediaType.APPLICATION_JSON})
#Path("test")
public Response myMethod(MyCustomObject myCustomObject) {
Inside MyCustomObject it has a list of another custom object which reside inside this as an inner class
public class MyCustomObject {
private List<MyInner> innerObjects;
public class MyInner {
private String property;
....
}
....
}
Request JSON object is passed as the POST body of the request. When I debug this I could get the MyCustomObject passed properly while I am sending the innerObjects list as null. But it seems its not picking this correctly when I have this array based structure there with a custom object. Additionally instead of this custom object array when I have a primitive type or a string based array the service works fine. How to deal with the above scenario.
It is probably because of the inner class.
Similar question here
Not sure what mapper you use (cxf default is jettison but it is all configurable), but the case is probably similar.
Great explanation here
non-static inner classes (including anonymous ones) have set of hidden variables added by compiler, passed via (hidden) constructor. And as a consequence, do not have zero-argument ("default") constructor

Why are static GWT fields not transferred to the client?

ConfigProperty.idPropertyMap is filled on the server side. (verified via log output)
Accessing it on the client side shows it's empty. :-( (verified via log output)
Is this some default behaviour? (I don't think so)
Is the problem maybe related to the inner class ConfigProperty.IdPropertyMap, java.util.HashMap usage, serialization or some field access modifier issue?
Thanks for your help
// the transfer object
public class ConfigProperty implements IsSerializable, Comparable {
...
static public class IdPropertyMap extends HashMap
implements IsSerializable
{
...
}
protected static IdPropertyMap idPropertyMap = new IdPropertyMap();
...
}
// the server service
public class ManagerServiceImpl extends RemoteServiceServlet implements
ManagerService
{
...
public IdPropertyMap getConfigProps(String timeToken)
throws ConfiguratorException
{
...
}
}
added from below after some good answers (thanks!):
answer bottom line: static field sync is not implemented/supported currently. someone/me would have to file a feature request
just my perspective (an fallen-in-love newby to GWT :-)):
I understand pretty good (not perfect! ;-)) the possible implications of "global" variable syncing (a dependency graph or usage of annotations could be useful).
But from a new (otherwise experienced Java EE/web) user it looks like this:
you create some myapp.shared.dto.MyClass class (dto = data transfer objects)
you add some static fields in it that just represent collections of those objects (and maybe some other DTOs)
you can also do this on the client side and all the other static methods work as well
only thing not working is synchronization (which is not sooo bad in the first place)
BUT: some provided annotation, let's say #Transfer static Collection<MyClass> myObjList; would be handy, since I seem to know the impact and benefits that this would bring.
In my case it's rather simple since the client is more static, but would like to have this data without explicitely implementing it if the GWT framework could do it.
static variables are purely class variable It has nothing to do with individual instances. serialization applies only to object.
So ,your are getting always empty a ConfigProperty.idPropertyMap
The idea of RPC is not that you can act as though the client and the server are exactly the same JVM, but that they can share the objects that you pass over the wire. To send a static field over the wire, from the server to the client, the object stored in that field must be returned from the RPC method.
Static properties are not serialized and sent over the wire, because they do not belong to a single object, but to the class itself.
public class MyData implements Serializable {
protected String name;//sent over the wire, each MyData has its own name
protected String key;
protected static String masterKey;//All objects on the server or client
// share this, it cannot be sent over RPC. Instead, another RPC method
// could access it
}
Note, however, that it will only be that one instance which will be shared - if something else on the server changes that field, all clients which have asked for a copy will need to be updated

EntityProxies with immutable ValueProxy properties -> "could not locate setter"

I'm trying to wrap my mind around RequestFactory, but I'm having some problems. I have an entityproxy that has a property which is a valueproxy of an immutable type (joda-time LocalDate), and I'm having problems using this entityproxy in any calls to the server.
I've made the property read-only by only including a getter for the property in the entityproxy, and only including getters for the primitive properties in the valueproxy.
However, as far as I can tell, If I use an entityproxy as an argument in a call to a service method, any referenced valueproxy is automatically marked as edited and all its properties are included in the delta?
This in turn causes ReflectiveServiceLayer to throw an exception about a missing setter on LocalDate.
I've been toying with the idea of implementing a ServiceLayerDecorator which overrides "setProperty" to get around this, but I'm not sure if that's a good solution. Is there any "proper" way to fix this? Ideally, I'd like AbstractRequestContext not to include immutable properties in calls to the server.
I'm using GWT 2.3
edit: I created a workaround like this, but I'm still unsure of whether this is the correct approach:
public class ImmutablePropertyFixServiceLayer extends ServiceLayerDecorator {
#Override
public void setProperty(Object domainObject, String property, Class<?> expectedType, Object value) {
Method setter = getTop().getSetter(domainObject.getClass(), property);
if (setter != null) {
super.setProperty(domainObject, property, expectedType, value);
} else {
//System.out.println(domainObject.getClass().getName() + "." + property + " doesn't have a setter");
}
}
}
EntityProxy objects have some way they can be easily retreived on the server, so when sending an object back to the server, just the ID is required. ValueProxy objects on the other hand can only be sent as the combination of all of their sub-values. When sending an immutable value back to the server, the server code doesn't know how to turn a proxy back into a server-side value.
I'd be concerned with your solution that you might not be correctly getting the same date on the server as was sent from the client.

GWT RequestFactory and multiple types

My GWT app has ten different kinds of entities. Right now I use plain old DTOs and transport them over GWT-RPC. This works well for cases like startup - I can pack them all into a single request.
I'm looking at switching to RequestFactory because there are many times throughout the lifetime of the app (30 minutes, on average) when I just have to update one type of entity, and the unifying/bandwidth-saving features of RequestFactory are appealing. BUT: I don't see a way to download all of my initialization data in a single request when the app loads. I don't want to have to make ten requests to fetch all of the init data for my ten entity types.
Is there a way to make a GeneralRequestContext, or something? I'd even be happy with a solution like:
public interface InitDataProxy extends EntityProxy
{
public UserProxy getInitUsers();
public OrganizationProxy getInitOrganizations();
...
}
public interface GeneralRequestContext extends RequestContext
{
Request<InitDataProxy> getInitData();
}
But this won't work because I don't want to have to actually back InitDataProxy with anything, I just want to use it to combine a bunch of different types of Proxies in a single request.
So: Is there a way to receive multiple, unrelated types of EntityProxy in a single request?
I would also be happy enough making a normal gwt-rpc request to go outside of RequestFactory for this data, but I don't want to have to implement duplicate DTOs to run next to RequestFactory's proxies, and write custom code to copy the DTOs into them!
The InitDataProxy could extend ValueProxy instead, which doesn't require that the object on the server have any kind of id or version semantics. The domain-side InitData type could be an interface, possibly implemented with an anonymous type.
interface InitData {
User getUser();
Organization getOrgatization();
}
class InitService {
static InitData makeInitData() {
return new InitData() { ..... };
}
}
#ProxyFor(InitData.class)
interface InitDataProxy extends ValueProxy {
UserProxy getUser();
OrganizationProxy getOrganization();
}
#Service(InitService.class)
interface Init extends RequestContext {
Request<InitDataProxy> makeInitData();
}