Saving List<EntityProxy> in GWT RequestFactory - gwt

I want to save a list of entity objects in RequestFactory. Most of the time, i can find
RequestContext with Save(EntityProxy) alone and not with Save(List of EntitProxy).
Is it possible to do in GWT ?

In your RequestContext, add a method like
Request<Void> save(List<MyEntityProxy> proxies);
and have that map to a method like
public void save(List<MyEntity> entities)...
in your service class.
This may need to be static, depending on how you are using locators, and what kind of Request you are using. If this isn't working, can you post the full RequestContext (including annotations) and the error that occurs? It might give a hint as to why it isn't working correctly.

Related

Jersey 2: filters and #Context injections

I've the following question:
ContainerRequestFilter is a singleton, but reading this:
Jaxrs-2_0 Oracle Spec
in chapter 9.2, they say:
Context is specific to a particular request but instances of certain JAX-RS components (providers and resource classes with a lifecycle other than per-request) may need to support multiple concurrent requests. When injecting an instance of one of the types listed in Section 9.2, the instance supplied MUST be capable of selecting the correct context for a particular request. Use of a thread-local proxy is a common way to achieve this.
In the chapter 9.2, the HttpServletRequest is not mentioned.
So the question is: is it safe in terms of concurrency to inject the HttpServletRequest inside a custom ContainRequestFilter?
I mean this:
#Provider
#PreMatching
public class AuthenticationFilter implements ContainerRequestFilter {
#Context private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// This is safe because every thread call the method with its requestContext
String path = requestContext.getUriInfo().getPath(true);
// Is this safe? The property request is injected by using #Context annotation (see above)
String toReturn = (String)request.getAttribute(name);
[...]
}
I did some empirical tests on my IDE in debug mode, sending with two different browsers two different and concurrent requests and it seems to work well; I noticed that the filter's instance is ever the same (it's a singleton), but the injected HttpServletRequest is different in the two cases.
I readed even this thread: How to access wicket session from Jersey-2 request filter? and it seems that my tests are confirmed.
But I still have doubts.
Confirm?
Yes it's safe. To understand the problem, you should understand how scopes work. In any framework that deals with scopes (and injection), the feature is implemented similarly. If an object is in a singleton scope and another object in a lesser scope needs to be injected, usually a proxy of the object will be injected instead. When a call is made on the object, it's actually a call on the proxy.
Though the spec may not mention the HttpServletRequest specifically, most JAX-RS implementation have support for this. With Jersey in particular, if this was not possible (meaning the object is not proxiable), then you would get an error message on startup with something like "not within a request scope". The reason is that the ContainerRequestFilter is created on app startup, and all the injections are handled at that time also. If the HttpServletRequest was not proxiable, it would fail to inject because on startup, there is no request scope context.
To confirm that it is not the actual HttpServletRequest and is a proxy, you can log the request.getClass(), and you will see that it is indeed a proxy.
If you are unfamiliar with this pattern, you can see this answer for an idea of how it works.
See Also:
Injecting Request Scoped Objects into Singleton Scoped Object with HK2 and Jersey

Implementing Hypermedia in RESTful JAX-RS Apache CXF

I am working in a RESTful application developed in Apache CXF and I would like to introduce hypermedia functionality to it.
Most of our jaxrs:serviceBeans follow this template:
#GET
#Path("/{exampleId}")
public ExampleJSON get(#PathParam("exampleId") Integer exampleId) {
ExampleJSON example;
// Load data from repository here...
// Add link to self.
String href = javax.ws.rs.core.Link.fromResource(ExampleService.class).build().getUri().toString();
// HypermediaLink is a custom object to hold a "href" and "rel" strings
HypermediaLink linkToSelf = new HypermediaLink();
linkToSelf.setHref(href + example.getId());
linkToSelf.setRel("self");
// Inherited method, just adds a HypermediaLink to a collection in the parent class
example.addHypermediaLink(linkToSelf);
// Return JSON compatible object, JACKSON will serialize it nicely.
return example;
}
This is the basic concept. Keep in mind that I simplified this code for explanation purposes; so, it can be easily understood.
This code works fine; but I am wondering if there is a better way to do this with Apache CXF. I have some ideas for how to enhancing it; however, it will require some custom annotations.
I see some examples using Jersey, but I would like to stick with Apache CXF.
Any help would be appreciated.
Thanks
I would leverage some features of JAX-RS and / or Jackson to implement the link adding under the hood at the serialization level. So you wouldn't need to have a specific field for the link within the bean itself.
You could implement a custom MessageBodyWriter to generate a different JSON payload (for example) for your POJOs than the default. So you could dynamically add the link.
See this answer for more details: How to write an XML MessageBodyWriter provider with jersey.
If you use Jackson for the serialization, you could implement a custom serializer. Note that this is generic and will work for all supported format of Jackson.
Below is a sample code:
public class LinkBeanSerializer extends JsonSerializer<SomeBean> {
#Override
public void serialize(SomeBean bean, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
// Fields
jgen.writeNumberField("id", bean.getId());
// Things could be generic using reflection
// Link
String href = javax.ws.rs.core.Link.fromResource(SomeBean.class).build().getUri().toString();
HypermediaLink linkToSelf = new HypermediaLink();
linkToSelf.setHref(href + bean.getId());
linkToSelf.setRel("self");
jgen.writeObjectField("hypermediaLink", linkToSelf);
jgen.writeEndObject();
}
}
Note that we could make this serializer more generic I think (something like extends JsonSerializer<Object>)
See this answer for more details: Processing JSON response using JAX-RS (how to register the custom serializer within JAX-RS, ...).
Perhaps implementing a WriterInterceptor could solve your problem but there is impact on the beans since you need to have field hypermediaLink. The interceptor could be responsible of filling the field.
See this answer for more details: Jersey Update Entity Property MessageBodyWriter.
IMO the more convenient solution is the second one. It's transparent and support all the formats supported by Jackson.
Hope it helps you,
Thierry

Apache Tiles and Spring Model Objects

The Header section (Apache Tiles Attribute) is shared by several views. It has a form that expects an Object when the page is loaded and complains if the Object is missing. At the moment I am placing the Object in a Model and passing it to the View using the Controller every time I create a view that inherits this layout.
This approach seems rather tedious as i have repeated lines all over the Controller. I'd like to be able to add it once and be done with.
I am not too familiar with Apache Tiles there maybe a simple solution that I am not aware of.
Looking for some helpful tips.
Thanks
You can use the HandlerInterceptorAdapter class and the postHandle method to achieve something like that. By cons, you will need to define a rule that will help you to know when the object need to be add to the model, it can be the path or something in the url, it depends on how your template is organized. Here an example of an interceptor that is doing something like that.
The interceptor defenition :
<mvc:interceptors>
<bean class="your.package.HeaderModelInterceptor"/>
</mvc:interceptors>
The interceptor class :
public class HeaderModelInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// Check if you need to add the object
if (Your rule) {
modelAndView.addObject("headerObject", headerObject);
}
super.postHandle(request, response, handler, modelAndView);
}
}
You have a couple of options to do this. Off the top of my head you could.
Use Tiles view preparers, simple example here
Use a mechanism like Spring interceptors or AOP to automatically add your object to the Model instead of repeating the code everywhere
It really depends on the nature of the object you're adding and how much context it needs.

What gets send to the server with request factory

I have problem to understand what does Request factory send to server. I have a method
Request<NodeProxy> persist(NodeProxy node)
NodeProxy is an Object from tree like structure (has child nodes and one parent node, all of type NodeProxy). I'v change only one attribute in the node and called persists.
The question now is what gets send to the server?
In the dock here https://developers.google.com/web-toolkit/doc/latest/DevGuideRequestFactory
there is:
"On the client side, RequestFactory keeps track of objects that have been modified and sends only changes to the server, which results in very lightweight network payloads."
In the same dock, in the chapter Entity Relationships, there is also this:
"RequestFactory automatically sends the whole object graph in a single request."
And I'm wondering how should I understand this.
My problem:
My tree structure can get quete big, lets say 50 nodes. The problem is that for update of one attribute the method
public IEntity find(Class<? extends IEntity> clazz, String id)
in the class
public class BaseEntityLocator extends Locator<IEntity, String>
gets called for each object in the graph which is not acceptable.
Thank you in advance.
The problem you're facing is that RequestFactory automatically edit()s proxies when getting properties, and there's a bug when constructing the request payload that makes the whole graph of proxies to be implicitly edited that way, even if you didn't call the getter yourself.
That bug has many repercussions, including false-positives in RequestContext's isChanged(): http://code.google.com/p/google-web-toolkit/issues/detail?id=5952
I have great hopes that this will be fixed in GWT 2.5 (due in the next weeks).

Jersey Guice Accessing Post Parameters

I have a Jersey client that is hooked up using Guice. Really hooked up :)
The resources are also created using Guice.
Something like:
#Inject
class TestResource {
#Inject DataFatcher fetcher,
...
...
}
Now, DataFetcher object is created using Guice and has deep nested guice-created objects using composition. Now, some of these object need access to parameters passed over using POST.
I have a HttpServletModule that does that for me. I I thought that does the right work.
HttpServletModule.java
Map<String, String[]> providerRequestParametersMap(HttpServletRequest reuquest) {
request.getParametersMap()
}
Now, unfortunately, It looks like Jersey, has already intercepter the request and removed the POST parameters from the request parameters Map. So, this Map of mine is empty.
How, can I get access to the POST Parameters in Guice ? I do not want to Inject the Form of MultivaledMap in the Resource directly, since that will need to be passed down all the way from the Resource which will mess up my design.
Any tips greatly appreciated. I can think of creating a Filter that intercepts the HttpServletRequest before the Jersey filters kicks in. Hoping that there is a better,easier solution :).
The easiest solution is probably a servlet Filter that does what you suggest: intercepting the HttpServletRequest before it's handled by Jersey and setting data in a request-scoped object.
If you're using Guice Servlet, filtering is at least a few keystrokes less setup than it is in web.xml.
If you'd prefer a Jersey-only solution, you could use a ContainerRequestFilter. This gives you access to ContainerRequest, which in turn provides you with a Form (a javax.ws.rs.core.MultivaluedMap).