How can I get the oldObject at any point of time? - java

Let say I have the following POJO
public class Plan{
private Long id;
private String name;
//other fields,getters, builder..
}
Now let say there is some Plan which already exist in db.
Now I am trying to modify/update various fields of this particular Plan by using the restAPI(api/v1/Plan/123).
Now we use Jackson here,so I will get the updated Plan object.I will be validating this updated Plan object and if all good will persist in the db.
Till here there is no issue.
But we using an internal service to audit this,i.e what all details got modified in this particular Plan and done by whom at what time etc.
For ex:Plan name changed from (Plan1 to Plan2)
Internal service will accept argument as (oldPlan,newPlan).
Now how can I get the oldPlan from the newPlan object?[Since the file which I have now got the method as public Plan update(Plan newPlan),inside this method only we will be calling an internal service method which requires oldPlan]
Constraints:
1.I should not fire the query getting the id from the newPlan,since that will be duplicate query coz it was already queried when creating newPlan object using jackson.
2.I should not change the update method signature and in update method the plan object which we receive via argument is the object which got updated details in it.
What I have in my mind is:
a)Having the Plan object itself in the POJO ,so that when I get newPlan.getPlan() will return the oldInstance?
The above approach can be done but I am not sure abt this.Whats the best approach to achieve this?

Related

Access user defined method properties on query - Esper

I implemented a query where i mined data from a database but i have to change it so i mine my data from a custom function in my code. I read the documentation and added the annotation import on the configuration. The query throws that error:
Failed to resolve event type, named window or table by name 'path.to.my.class.customfunction'
I don't know the type that my function have to return but i tried Arraylist and Hashmaps with key an integer and value a custom class and didn't work.
My final query want to look like this :
select * from LocationEvent as loc,
***CustomFuntion()*** as product
where loc.id=product.id ;
I kept the structure i used for database connection. I don't know if there is another way to solve this. Thanks.
EDIT: I managed to make call the custom function with that query :
select path.to.class.getProducts() as product from pattern[every timer:interval(3 sec)]
My function right now return an ArrayList and the query returns this:
[Product{ProductID=124,.....,},Product{...}]
So now my problem is that i can't access properties of Product on the query like products.ProductID
If you want to have a custom function in the from-clause you can use the "method:". The docs have this described here: Accessing Non-Relational Data via Method. The Esper runtime then calls your method to get events/rows.

OData Service with Olingo V4 and MySQL database connection

I was following some example in which we can able to build OData service with Olingo from Java (maven project). The provided example doesn't have any database interaction. They are using some Storage.class, which contains hard codded data.
You can find sample code on git. please refer example p0_all in provided url.
Does anyone knows how we can connect git example with some database and furthermore perform CRUD operations
Please do help me with some good examples or concept.
Thanking you in advance.
I recently built an oData producer using Olingo and found myself similarly frustrated. I think that part of the issue is that there really are a lot of different ways to build an oData service with Olingo, and the data access piece is entirely up to the developer to sort out in their own project.
Firstly, you need an application that has a database connection set up. So completely disregarding Olingo, you should have an app that connects to and can query a database. If you are uncertain of how to build a java application that can query a MySQL datasource, then you should Google around for tutorials that are related to that problem and have nothing to do with Olingo.
Next you need to write the methods and queries to perform CRUD operations in your application. Again, these methods have nothing to do with Olingo.
Where Olingo starts to come in to play is in your implementation of the processor classes. EntityCollectionProcessor, EntityProcessor etc. (note that there are other concerns such as setting up your CsdlEntityTypes and Schema/Service Document etc., but those are outside the scope of your question)
Lets start by looking at EntityCollectionProcessor. By implementing the EntityCollectionProcessor class you need to override the readEntityCollection() function. The purpose of this function is to parse the oData URI for the entity name, fetch an EntityCollection for that Entity, and then serialize the EntityCollection into an oData compliant response. Here's the implementation of readEntityCollection() from your example link:
public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat)
throws ODataApplicationException, SerializerException {
// 1st we have retrieve the requested EntitySet from the uriInfo object
// (representation of the parsed service URI)
List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0);
// in our example, the first segment is the EntitySet
EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
// 2nd: fetch the data from backend for this requested EntitySetName
// it has to be delivered as EntityCollection object
EntityCollection entitySet = getData(edmEntitySet);
// 3rd: create a serializer based on the requested format (json)
ODataSerializer serializer = odata.createSerializer(responseFormat);
// 4th: Now serialize the content: transform from the EntitySet object to InputStream
EdmEntityType edmEntityType = edmEntitySet.getEntityType();
ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).build();
final String id = request.getRawBaseUri() + "/" + edmEntitySet.getName();
EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with().id(id).contextURL(contextUrl).build();
SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, entitySet, opts);
InputStream serializedContent = serializerResult.getContent();
// Finally: configure the response object: set the body, headers and status code
response.setContent(serializedContent);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
}
You can ignore (and reuse) everything in this example except for the "2nd" step:
EntityCollection entitySet = getData(edmEntitySet);
This line of code is where Olingo finally starts to interact with our underlying system, and the pattern that we see here informs how we should set up the rest of our CRUD operations.
The function getData(edmEntitySet) can be anything you want, in any class you want. The only restriction is that it must return an EntityCollection. So what you need to do is call a function that queries your MySQL database and returns all records for the given entity (using the string name of the entity). Then, once you have a List, or Set (or whatever) of your records, you need to convert it to an EntityCollection.
As an aside, I think that this is probably where the disconnect between the Olingo examples and real world application comes from. The code behind that getData(edmEntitySet); call can be architected in infinitely different ways, depending on the design pattern used in the underlying system (MVC etc.), styling choices, scalability requirements etc.
Here's an example of how I created an EntityCollection from a List that returned from my query (keep in mind that I am assuming you know how to query your MySQL datasource and have already coded a function that retrieves all records for a given entity):
private List<Foo> getAllFoos(){
// ... code that queries dataset and retrieves all Foo records
}
// loop over List<Foo> converting each instance of Foo into and Olingo Entity
private EntityCollection makeEntityCollection(List<Foo> fooList){
EntityCollection entitySet = new EntityCollection();
for (Foo foo: fooList){
entitySet.getEntities().add(createEntity(foo));
}
return entitySet;
}
// Convert instance of Foo object into an Olingo Entity
private Entity createEntity(Foo foo){
Entity tmpEntity = new Entity()
.addProperty(createPrimitive(Foo.FIELD_ID, foo.getId()))
.addProperty(createPrimitive(Foo.FIELD_FOO_NAME, foo.getFooName()));
return tmpEntity;
}
Just for added clarity, getData(edmEntitySet) might look like this:
public EntityCollection getData(String edmEntitySet){
// ... code to determine which query to call based on entity name
List<Foo> foos = getAllFoos();
EntityCollection entitySet = makeEntityCollection(foos);
return entitySet;
}
If you can find an Olingo example that uses a DataProvider class, there are some basic examples of how you might set up the // ...code to determine which query to call based on entity name. I ended up modifying that pattern heavily using Java reflection, but that is totally unrelated to your question.
So getData(edmEntitySet) is a function that takes an entity name, queries the datasource for all records of that entity (returning a List<Foo>), and then converts that List<Foo> into an EntityCollection. The EntityCollection is made by calling the createEntity() function which takes the instance of my Foo object and turns it into an Olingo Entity. The EntityCollection is then returned to the readEntityCollection() function and can be properly serialized and returned as an oData response.
This example exposes a bit of the architecture problem that Olingo has with its own examples. In my example Foo is an object that has constants that are used to identify the field names, which are used by Olingo to generate the oData Schema and Service Document. This object has a method to return it's own CsdlEntityType, as well as a constructor, its own properties and getters/setters etc. You don't have to set your system up this way, but for the scalability requirements of my project this is how I chose to do things.
This is the general pattern that Olingo uses. Override methods of an interface, then call functions in a separate part of your system that interact with your data in the desired manner. Then convert the data into Olingo readable objects so they can do whatever "oData stuff" needs to be done in the response. If you want to implement CRUD for a single entity, then you need to implement EntityProcessor and its various CRUD methods, and inside those methods, you need to call the functions in your system (totally separate from any Olingo code) that create(), read() (single entity), update(), or delete().

Spring MongoRepository is updating or upserting instead of inserting

I'm using a :
org.springframework.data.mongodb.repository.MongoRepository
I start with an empty DB and create an object with _id = 1234 for example, and set some other String field to hello for example, and then do:
repository.save(object);
All is well, it saves the document in MondoDB.
I create a NEW object, set the same _id = 1234 but set the other String field to world and then to another save :
repository.save(newObject);
Results : the save works but updates the original object.
Expected results: This should fail with a DuplicateKeyException as _id is unique and I am using 2 separate objects when doing each save.
Defect in spring or am I doing something wrong ???
Save, by definition, is supposed to update an object in the upsert style, update if present and insert if not.
Read the save operation documentation on the MongoDb website
The insert operation in mongodb has the behavior you expect, but from the MongoRepository documentation it appears that insert is delegated to save so it won't make any difference. But you can give that a try and see if it works for you. Otherwise you can just do a get before to check if the object exists, since it is an index lookup it will be fast.
Edit: Check your repository version, insert was introduced in version 1.7.
the application shall update only when you have #Id annotation for one of the field, after long difficulty had found this
#Document(collection="bus")
public class Bus {
// #Indexed(unique=true, direction=IndexDirection.DESCENDING, dropDups=true)
#Id
private String busTitle;
private int totalNoOfSeats;
private int noOfSeatsAvailable;
private String busType;
}
but somehow I could not use
#Indexed(unique=true, direction=IndexDirection.DESCENDING, dropDups=true)

Hibernate gets null for entity instance variables?

I'm trying to implement a feature requires the form to load data for the logged in user.So I wrote a query to get these data for this user ID,Here is a code snippet from the school entity class:
public class ShSchool implements java.io.Serializable {
private long schoolId;
private GsDistrict gsDistrict;
}
I tried to get the data using the following query:
session.createQuery("from ShSchool where schoolId="+schoolId).list();
The problem is that I got values for primitive instance variables and got null for any other data types such as GsDistrict, So what is wrong and how could I got these objects values?
Thanks
Possible causes:
The gsDistrict is indeed null for that particular user, check the DB to make sure it's not.
The Hibernate mappings are incorrect.
The gsDistrict is lazy loaded and you're accessing it outside the Hibernate session. In this case, however, I'd expect an exception to be thrown.
Please include the Hibernate mappings, the problem may be there.

Submitting / binding partial objects with spring mvc

The Spring MVC binding mechanism is powerful, but I'm now confronted with a trivial issue that I wonder how to resolve:
User JPA entity, that is used for the binding and validation as well (i.e. throughout all layers)
"Edit profile" page, that is not supposed to change the password or some other entity properties
Two ways that I can think of:
Using the same object
use #InitBinder to configure a list of disallowed properties
obtain the target user (by id)
then use a reflection utility (BeanUtils) to copy the submitted object to the target object, but ignore null values - i.e. fields that are not submitted
Introduce a new object that has the needed subset of fields, and use BeanUtils.copyProperties(..) to merge it to the entity.
Alternatives?
I've found that as soon as your web model starts to diverge from your business layer in function, it's best to use a view layer object (a model object) to collect, or display the data
the entity:
public class com.myapp.domain.UserEntity {
}
the model object:
public class com.myapp.somesite.web.SomeSiteUserModel {
public static SomeSiteUserModel from(UserEntity userEntity) {
... initialize model ...
}
public UserEntity getModelObject() {
... get entity back ...
}
}
now all view based operations can hand off processing to the internal model object if that makes sense, otherwise it can customize them itself. Of course the problem with this is you have to re-write all the getters and setters you want for the entity (an issue that I've had to deal with, that is annoying) unfortunately that is a bit of a Java language issue
I just checked up with two of the last Spring projects I have worked on and in both places the following approach is taken:
In the JSP page for the form the change password field has a name that does not match the name of the password field in the User bean, so that it doesn't get mapped to the bean. Then in the onSubmit method there is a separate check whether a new password has been submitted, and if it has been, the change is reflected explicitly.
Поздрави,
Vassil
You can read the object from the database first and bind then the request. You can find an example at FuWeSta-Sample.
It uses a helper-bean which must be initialized by Spring.

Categories