I am making use of Auditing with Spring Data JPA to automatically update the created by time stamp. I have a requirement, where i have to migrate some data for which the created by date should be updated with the value am setting through the application. I have debugged the code, the values are setting properly. But while calling
fooRepository.save(fooEntity)
The created by is getting overridden by the auto generated time stamp.
Is it possible to override the value?
I am also having a #Transactional annotation in Service level. While debugging i can see the date is getting replaced on the Entity returned by the save repository method.
It is not a better way but you can follow.
First, create the entity
fooRepository.saveAndFlush(fooEntity);
and then update the createdAt data then save the entity again.
fooEntity.setCreatedAt(yourTime);
fooRepository.saveAndFlush(fooEntity);
Create new enity without #CreatedDate and new repository for that new entity.
Only use that new repository when you need to edit CreatedDate or LastModifiedDate
This seems to be a bad solution but is the only solution I can think of now.
I am looking for better solution to this problem
Related
The ask is to modify the password of a mongodb connection at runtime in a spring boot project. For example let's assume a mongodb connection is established while starting the application with password 'xyz'.I would like to modify the password at runtime by lets say hitting an api.
I have tried following solutions so far to tackle this issue:
Replacing mongoTemplate bean at runtime: Tried creating a new mongoTemplate Bean with new password at runtime and replaced it in the context using the methods given in following link. The issue with this approach is that the bean is getting refreshed only once. Ideally it should work everytime when the api to update password is being called.
Updating password in mongoCredentials: One of the obvious approach is to update the password directly in mongoCredentials since mongoTemplate uses mongoCredential class to store the credentials information.But the issue is that the password field in MongoCredentials class is 'final static' so we cannot update it even with reflections. Even though there are some tricks to update the final static fields but i'm looking for a more acceptable solution.
There is #RefreshScope in Spring Cloud project exactly for your purpose. Here is Spring's documentation about how it works: https://cloud.spring.io/spring-cloud-static/spring-cloud.html#_refresh_scope.
So all you need to do is update Environment and call org.springframework.cloud.context.scope.refresh.RefreshScope#refresh or org.springframework.cloud.context.scope.refresh.RefreshScope#refreshAll when you need to refresh your context.
When using Spring Couchbase connector I can easily get version for optimistic locking by having this in my class:
public class MyClass {
#Version
private String version;
.... rest of class omitted ....
}
I'm now trying to find a similar way to get and be able to modify the meta data for expiration. I'm unable to find how to do this.
Can someone please give an example? Thanks!
With spring data couchbase library (until the latest Version 3.0.8.RELEASE), document expiry can be defined by using #Document(expiry = 10) or #Document(expiryExpression = "${valid.document.expiry}") on the class. There is also an optional boolean attribute touchOnRead which needs to be added with #Document, which would reset the expiry timer whenever the document is directly read. Please note that currently the expiry of an existing document cannot be read/modified directly with this library. One way would be to access the below APIs exposed by Couchbase's own java SDK (com.couchbase.client.java)
getAndTouch - allows you to retrieve a document while modifying its expiration time
touch - allows you to modify a document’s expiration time without otherwise accessing the document
You can find the method signatures of the above two here : http://docs.couchbase.com/sdk-api/couchbase-java-client-2.2.4/com/couchbase/client/java/Bucket.html
The above two APIs can be accessed via the spring data couchbase library as follows
couchbaseTemplate.getCouchbaseBucket().touch(...)
couchbaseTemplate.getCouchbaseBucket().getAndTouch(...)
The getCouchbaseBucket() method of the spring library returns a reference to com.couchbase.client.java.Bucket using which the touch and getAndTouch methods can be used.
I have an (put) endpoint in some micro service lets call it A which can call from outside of the domain and from another micro service inside the same domain.
I implemented if-match header with #Version annotation and working just fine but i need additional feature such as; they want to call this endpoint from another micro service at the same domain with "*" and i have to tell JPA to accept request without optimistic-locking.
How could i force JPA to update if the request come from same domain with "*"?
Ok i just fixed this. We were using JPA totaly wrong when updating entity. When update some entity you should just get this entity from repo and set its fields. For example;
FooData comes service layer from controller and FooEntity comes from repo. You should use FooData to just check fields of FooEntity and set null to (#Version) tagged row_version. This means jpa can automaticaly increase number and worked well to me.
Wrong Behaviour: Convert FooData into BarEntity type-> Set new values to BarEntity and repository save the new entity.
If i'm still doing wrong please update me, I'll be appreciated.
I am converting my Java object to Map using Spring Integration ObjectToMapTransformer's transformPayload().
Everything works fine except that the Instant fields in my object are getting broken into epochSecond and nano, which in turn throws exception while persisting in data-store (MongoDB).
This is the Spring Integration JsonObjectMapper being used to convert the Object to Map:
private final JsonObjectMapper<?, ?> jsonObjectMapper = JsonObjectMapperProvider.newInstance();
My question is how can I configure date format for the above mapper. Just like Jackson's ObjectMapper::configure(), do we have any similar options here?
I cannot find any, neither in source code nor on internet!!
I also tried enabling/disabling spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS in my application.properties, but no joy!
I have jackson-datatype-jsr310 dependency in my pom.xml
How to get the Instant in correct format?
I think we should add support for custom JsonObjectMapper injection. That way you would be able to build Jackson2JsonObjectMapper based on desired ObjectMapper.
Please, raise a JIRA ticket on the matter and don't hesitate with the contribution: https://github.com/spring-projects/spring-integration/blob/master/CONTRIBUTING.adoc
Meanwhile as a workaround I'd suggest a pair of ObjectToJsonTransformer/JsonToObjectTransformer:
.transform(Transformers.toJson(jsonObjectMapper(), ObjectToJsonTransformer.ResultType.NODE))
.transform(Transformers.fromJson(Map.class, jsonObjectMapper()))
In my application, when user logs in to the system the system reads some setting from DB and stores them on user's session. The system is performing this action by a JPA query using EclipseLink (JPA 2.0).
When I change some settings in DB, and sign in again, the query returns the previous results. It seems that EclipseLink is caching the results.
I have used this to correct this behavior but it does not work:
query.setHint(QueryHints.cache_usage,cacheUsage.no_cache);
If you want to set query hints, the docs recommend doing:
query.setHint("javax.persistence.cache.storeMode", "REFRESH");
You can alternately set the affected entity's #Cacheable annotation
#Cacheable(false)
public class EntityThatMustNotBeCached {
...
}
If you're returning a some kind of configuration entity and want to be sure that data is not stale, you can invoke em.refresh(yourEntity) after returning the entity from query. This will force the JPA provider to get fresh data from the database despite the cached one.
If you want to disable the L2 cache you can use <shared-cache-mode>NONE</shared-cache-mode> within <persistence-unit> in persistence.xml or use Cacheable(false) directly on your configuration entity.
If you're returning plain fields instead of entities and still getting stale data you may try clearing the PersistenceContext by invoking em.clear().