Null values update with Spring Rest Resource - java

There is a class annotated with RestResource (Spring 3.1, Jackson 2.3).
When we try save object A like that
A: {"prop1":1, "prop2":2}
it saved successfully.
We have following code:
A.setProp2(null);
EntityService.patch(A);
A: {"prop1":1, "prop2":null}
After EntityService.patch(A) execution there is no changes in DB (Oracle 11g), but we want that in DB prop2 will be equals to null too.
Is it a normal behaviour (I think maybe yes, because null-value may understanding like not changed)?
Is there a simple way to change this behaviour?

When speaking about the HTTP verbs, the PATCH request describes the differences that should be made to the existing object. It is made so that you can easily create partial updates without exposing a particular resource property throught REST.
In Spring framework, in the context of PATCH request, the null value of a property means no change to the property should be made. I guess that spring data rest transpons this logic to the service layer, so in order to actually update your resource with the null value you should issue a call corresponding to the PUT semantics

So, the answer above is right.
Unfortunately, PUT method update all fields and in some cases it maybe a bad solution. For example if we have many nulls in JSON-object, which wasn't modified.
To make Spring PATCH update null values, only when it's change, the best way that I found is extend DomainObjectMerger class.
It is a bean of REST MVC config, in which we can override method merge (entity.doWithProperties(new SimplePropertyHandler() {}).
In this method we can add addition condition like
sourceValue != targetValue;
independent on null value of sourceValue variable.

Related

Spring Data Repository handle null results or entity reading permissions

I've managed to get Spring Data JPA up and running with my current project. Everything has been going fairly smooth up until now.
I was wondering, is there a way to handle Spring Data Repository responses inside the actual Repository/Base repository implementation? (Or perhaps in an interceptor?)
For instance: I have the need to check if any results were returned from my repository methods, and throw an exception if not like so:
(Preferably keeping the 'magic' of Spring data and not having to implement every repository method)
public interface MyRepository<T,ID> extends CrudRepository<T,ID> {
List<T> findByName(String name);
}
In this case I'd want to throw an exception if the resulting List<T> was null/empty.
Example 2: I have the need to check permission to read, to make sure I have the right to read the requested object from the database. Same thing goes here, I want to inspect / intercept the repository result and find out if the entity instance is the right one considering my context. (For security reasons)
TL;DR Is there any way of "intercept"/inspect the resulting entities/list from a repository method without having to implement ALL magic findBy... methods from all repositories? Perhaps in the base repository implementation or via an interceptor of some kind?
Regards
EDIT I have seen the answer in this particular SO question and I was wondering if there's another way of doing it, which doesn't involve the use of a custom implemented MethodInterceptor?
Regards

Migrate Struts-Tiles to Spring + tiles 3

I'm migrating to SpringMVC and Apache Tiles 3 from a Strut1 + Tiles project. I know only a little about Struts1+Tiles, it is too old and I'm stuck in Controller and ComponentContext in Struts-tiles. According to document from apache website, it was replaced by ViewPreparer and AttributeContext but I dont know the following line means:
ComponentContext compContext=(ComponentContext)pageContext.getAttribute(ComponentConstants.COMPONENT_CONTEXT,PageContext.REQUEST_SCOPE);
What is ComponentConstants.COMPONENT_CONTEXT? and how to change ComponentContext to AttributeContext
Please Help, Thanks.
Bidi, there are 2 ways of getting an AttributeContext:
The first one, like mck stated: through "org.apache.tiles.AttributeContext.STACK" key of request scope. However, the value is a STACK that contains 2 elements of AttributeContext type. The one we need is the first element. IMHO, this way is limited because since the data structure is a stack, getting also mean removing from the stack according to FIFO rule, so you can use the object for only once.
I am using the second way in my project. Because the execute() method of ViewPreparer already have a parameter of AttributeContext type, and this method is always called each time a page is rendered, so you can use this object to do the thing you want (or put it in request) when overriding the method.
AttributeContext is just a collection of key/value pairs. Normally, people use it to get access to some values which are attributes in the template, so fetching the values and putting them to the request can save the overhead. You can also create some static properties of the inheriting class and setting the values to them.
With the Spring-4 and Tiles-3 integration set up (there's spring docs on this as well as a number of good tutorials around) then the properties you put into spring's model map will be available in your jsps, this is not related to the AttributeContext.
AttributeContext only the other hand is (basically) only for holding the map of attributes. Attributes here are defined within a definition, used to identify template or string attributes (as is typically declared in you xml definitions), and come with properties of role, renderer, expression, and/or value.
If AttributeContext is what you are after: you can get hold of it through the current tilesContainer, and to get hold of the current container use the static TilesAccess, eg
TilesContainer tileContainer = TilesAccess.getCurrentContainer(request);
AttributeContext attributeContext = tilesContainer.getAttributeContext(request);
Bidi,
take a read of http://tiles.apache.org/framework/tutorial/advanced/runtime.html
particular the "Runtime Composition using APIs" section.
TilesContainer container = TilesAccess
.getContainer(request.getSession().getServletContext());
Request tilesRequest = new ServletRequest(
container.getApplicationContext(),
request,
response);
otherwise i suggest you take a dive into the Tiles codebase, it's not complicated code, especially the TilesAccess, Request, ApplicationContext stuff.

How do you seed non scoped named bindings using Guice ?

Building a web based application using Guice and have this peculiar situation -
I am using a lot of method interceptors that are lightweight.
My question is - I have a named binding say "Operation.Current" the value of which needs to be changed when one of these interceptors executes within a single request thread. So the bound value changes multiple times within a single request thread. I need this value to be injected as I need.
Currently I am using
request.setAttribute(Key.get(Operation.class, Names.named("Operation.Current")).toString(), op);
in my GuiceFilter to initialize the value. And I want to replace this value when the interceptors execute.
So I need to re seed my value present in the request as an attribute multiple times through the request.
What is a better way to solve this issue ? Since I see that the value is not in a real sense RequestScoped. So ideally this value should be non scoped and bound the name.
But how do I change the value as I need outside a Guice Module ?
You cannot modify the module binding once you created the injector. If you know all instances in advance, try the MapBinder, otherwise consider using a provider-binding, then you can evaluate the required instance dynamically for each call.

Creating global initBinder using Spring

I am using Spring 3.2 and I am looking for a way that I can force controllers to specify which attributes allowed to be bound, so malicious users can not inject values into bound objects.
Spring recommends using setAllowedFields() to white-list / setDisallowedFields() to black-list.
Instead of doing manually this white-list, I want to do this dinamically, so I want to bound that attributes that are visible on the form.
So is it possible to get this white-list? Is there any way that I can get the visible attributes on the form?
Thanks.
You could implement a RequestDataValueProcessor especially the method processFormFieldValue. You could construct a collection of allowed field names, store this in the session.
Next you would extend the ConfigurableWebBindingInitializer and override the initBinder method. Which would retrieve the collection and pre-configure the WebDataBinder there.
And finally you would need some configuration to wire everything together.
Links
RequestDataValueProcessor javadoc
ConfigurableWebBindingInitializer javadoc

"Dynamic" java validation framework?

AFAIK JSR-303 is the standard bean validation system.
I don't know whether it could do validations like this (I guess no):
if an object has a deleted flag set, you cannot modify the object
you cannot change the start date property, after the date is passed
you cannot decrease some integer properties in the bean
So how can I handle validations, which depend on the previous state of an object?
I would like to solve problems like that in hibernate3.5 - spring3 - JPA2 environment.
Thanks
My solution was to mess with hibernate, reload the object to see the old state (after evicting the new object). This time I need some smarter solution...
I don't think this can be done using JSR 303 validation (or any other validation framework I've used). Validation is usually stateless - you pass it an instance of an object, and your validation framework tests things to make sure the current values of your object are valid. There's no real knowledge of previous states of the object.
You can do this - just not with validation. You could use a constrained property, or you could make this work using the proxy pattern or AOP.
It sounds like the fields which you want to validate (with regards to previous state) are all metadata about the records as opposed to real data. All of these fields (idDeleted, createdDate, etc.) are better left out of your domain layer and therefor do not require validation. I would put the logic for determining & setting these values in you data-access layer so that the systems using your repository interfaces do not need to know or care about getting them right.
If my assumption about these fields being meta-data is not correct and you have user-entered data which validation depends on previous state, then I do not think that an extra lookup for the previous values is absurd and should not be out of the question. It makes sense in your case. Hibernate itself does a lookup under then hood to determine whether to INSERT or UPDATE when using it's save function.
Hope you find a reasonable solution.
how can I handle validations, which depend on the previous state of an object?
I'm not 100% sure it's doable but the only way I can think of would be to create an object graph made of the "new state" and the "old-state" (transient) and to validate the object graph as a whole using custom constraints. That's at least what I would try.
I would probably create a transient field that says previous version which points to a copy of the data that represents its previous state. This object is created on construction but since it is marked as transient it is not serialized. Then do the validations against it.
Simplest implementation would be to add a method called makeACopy() which makes a copy of the object and put it into the field.
You can add complexity by implementing Clonable or creating a utility class that would do reflection, but that's up to you. I suggest makeACopy() and refactor later since it is easier to think about.
I don't know any ready-to-use solution either. As you suspect JSR-303 won't do the job, because it's validation is 'static'.
But...
An idea would be to use some AOP techniques to do that. So...
if an object has a deleted flag set, you cannot modify the object
This one I would implement as a proxy method registered around every setter. The proxy method would check the 'deleted' flag. If it was set to true, an exception would be thrown, otherwise the original method would be executed.
you cannot change the start date property, after the date is passed
This one is similar. This time you wouldn't access any other property in the intercepted setter, but the original (not changed yet) value of the field and setter argument.
you cannot decrease some integer properties in the bean
That one is the same as with the dates, the only difference is the date type (date vs integer).
One can argue if AOP is a good choice for this task, but still a solution. I am doubtful too.
One more concern is that I guess you would want to enforce these contraints on JPA entities. So using Spring AOP wouldn't be that easy, since the entities wouldn't be Spring managed.
A completely different approach is to put the validation checks into the setters of properties. The downside is that you would lose declarativeness.
Example:
public void setCounter(int newCounter) {
if (newCounter < this.counter) {
throw new IllegalOperationException("Cannot decrease the counter");
} else {
this.counter = newCounter;
}
}
You might want to look at OVal instead. We do this kind of validation all the time. Normally, it's done using the SimpleCheck where you get the object and the value and can do all kinds of cross-checking.

Categories

Resources