Spring Data Gemfire: How to set TTL for entry using annotation? - spring

I am trying to set timeout for 30 days (i.e. 2592000 seconds) for entries in a region.
In, gfsh I was able to do create region --name=employee --type=REPLICATE --enable-statistics --entry-time-to-live-expiration=2592000. To confirm, do we use #TimeToLiveExpiration for entry not for region. I do not want the region to be deleted. If this is for entry then curious how can we set for region? Thanks.
#ReplicatedRegion(name = "employee")
#EnableStatistics
#TimeToLiveExpiration(timeout = "2592000", action = "DESTROY") // is this for region or entry ??
#Data
public class Employee {
private String id;
}

Yes, both SDG's entity-level Expiration-based annotations, #TimeToLiveExpiration and #IdleTimeoutExpiration configure Region "entry" level expiration polices.
Technically, this is implemented as an CustomExpiry object (Javadoc) registered on the Region (e.g. "employees"). These annotations most definitely do NOT expire, or delete/remove the Region.
More information on configuring Apache Geode (GemFire) Expiration (policies) using SDG can be found here and here.

Related

Spring Data Rest - Set request timeout

I have a Visit entity which refers to a Patient entity by ManyToOne relationship. The repository for Visit is:
#RepositoryRestResource(collectionResourceRel = "visits", path = "visits", excerptProjection=VisitProjection.class)
public interface VisitRepository extends PagingAndSortingRepository<Visit, Long> {
#RestResource(path="all")
List<Visit> findByPatientIdContaining(#Param("keyword") String keyword);
}
When searching visits by patient ID with /visits/search/all?keyword=1 which may return millions of records, the query is forever pending and never ends. In the console there are dozens of hibernate sqls printed every second. How can I set the request timeout from server side?
I have tried:
And Transactional annotation with timeout attribute to repository method: (works a little but still takes long to timeout)
#RestResource(path="all")
#Transactional(timeout=2)
List<Visit> findByPatientIdContaining(#Param("keyword") String keyword);
add some timeout properties to application.properties: (just doesn't work at all):
spring.jpa.properties.hibernate.c3p0.timeout=2
spring.jpa.properties.javax.persistence.query.timeout=2
spring.mvc.async.request-timeout=2
server.connection-timeout=2
rest.connection.connection-request-timeout=2
rest.connection.connect-timeout=2
rest.connection.read-timeout=2
server.servlet.session.timeout=2
spring.session.timeout=2
spring.jdbc.template.query-timeout=2
spring.transaction.default-timeout=2
spring.jpa.properties.javax.persistence.query.timeout=2
javax.persistence.query.timeout=2
server.tomcat.connection-timeout=5
Okay, no one using your API is going to want millions of records in one hit so use the provided paging functionality to make the result set more manageable:
https://docs.spring.io/spring-data/rest/docs/3.1.6.RELEASE/reference/html/#paging-and-sorting
#RestResource(path="all")
Page<Visit> findByPatientIdContaining(#Param("keyword") String keyword, Pageable p);
Clients can specify the records they want the records returned by adding the params:
?page=1&size=5

Spring framework + Hazelcast , how to enable/disable cache using #Cacheable annotation

I am using Spring framework and hazelcast cache to cache REST APi at service layer. The api I am caching has #Cacheable annotation with cachename and keygenerator which works fine. I am looking for best way to enable/disable caching using application property or consul property. For that I am trying to pass the property in condition attribute of #Cachable annotation but is not working. With this approach I will end up passing same value in multiple place (wherever I am caching at API level). Is there any good way to handle such operation.
As an example here is a code snippet
#Cacheable(cacheNames = CacheName.MyCache1,keyGenerator = "customKeyGen")
public CachingObject myFirstAPI(String param1, String param2) {
}
Here the hazelcast cache will use customKeyGen and put value (CachingObject) returned by myFirstAPI . If I have to disable this operation , my current approach is to pass some value (read from application property) as condition so that it evaluate the flag/condition before creating cache and cache the value only if the condition is true i.e. cache is enabled, e.g.
#Cacheable(cacheNames = CacheName.MyCache1,keyGenerator = "customKeyGen", condition="${enableCache}")
public CachingObject myFirstAPI(String param1, String param2) {
}
In my case the expression language I am passing in condition throwing exception , which I will figure out why (It is currently throwing SpelEvaluationException, Property or field 'enableCache' cannot be found on object of type 'org.springframework.cache.interceptor.CacheExpressionRootObject' )
My question is , is this correct way to enable/disable caching ? Please suggest.
Try spring.cache.type == none. See https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html#boot-features-caching-provider-none

#Cacheable : how to pass a new attribute that can be used in my own KeyGenerator?

I need your expertise :)
I'm working on a application where method calls on a service need to be authenticated.
That means I want each method call to be cached with a key containing the username (to avoid for an unauthorized user to retrieve information cached by an authorized one).
With a personnalized KeyGenerator, all works fine.
Example of my key : username:USERNAME.appVersion:VERSION.METHOD.PARAM1.etc
But at some location, I got methods that retrieve a national content : this one will be the same for each user. And I want to avoid a cache key for each user asking for this content.
Example : appVersion:VERSION.METHOD.PARAM1.etc
So when I'm positioning my #Cacheable annotations, is there any way to set a new parameter in it ? The Key Generator will be able to catch it and know if he had to prefix the cache key name with user information or not.
Thanks for your help :)
Take care
I don't really understand what you're saying by "set a new parameter in it". That parameter should come from somewhere right?
KeyGenerator gives you access to the Method, the actual instance and the method arguments. You may want to have a specific KeyGenerator for this particular cache operation which is something that will be available as from Spring 4.1 but in the mean time you can implement a composite that invokes the right KeyGenerator instance based on the method or, for instance, an annotation you have created to flag it.
Thank you snicoll, that was crystal clear and you really helped me a lot :)
Waiting for Spring 4.1, my team and I decided to use a custom #SharedCache annotation.
Here is some code samples to help if someone is in the same situation.
Given an existing custom GenericKeyGenerator (he's building a custom cache key for each cached method invocation)
We have a new custom AuthenticatedGenericKeyGenerator : he's inherited from GenericKeyGenerator and simply prefixing the cache key with user information
The application is now using AuthenticatedGenericKeyGenerator by default :
<cache:annotation-driven key-generator="keyGenerator"/>
<bean id="keyGenerator" class="your.package.AuthenticatedGenericKeyGenerator" />
AuthenticatedGenericKeyGenerator.java in details :
public class AuthenticatedGenericKeyGenerator extends GenericKeyGenerator {
public AuthenticatedGenericKeyGenerator() {
super(...);
}
#Override
public Object generate(final Object target, final Method method, final Object... params) {
String cacheKey = super.generate(target, method, params).toString();
if(!method.isAnnotationPresent(SharedCache.class)) {
cacheKey = "user:" + some user information + "." + cacheKey;
}
return cacheKey;
}
}
Our custom #SharedCache annotation :
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#Inherited
#Documented
public #interface SharedCache {
}
Now we just have to annotate #Cacheable methods with an extra #SharedCache if we want the cache key to be shared and not be unique (with an user id for example).

How can I configure Grails id columns to use UUID on Oracle?

I'd like to use a 128-bit UUID rather than Long for the id field on all of my Grails domains. I'd rather not have to specify all of the mapping information on every domain. Is there a simple way to achieve this in a generic/global way? I'm using Grails 2.3.x, the Hibernate 3.6.10.2 plugin, the Database Migration Plugin 1.3.8, and Oracle 11g (11.2.0.2.0).
There seem to be a number of questions related to this, but none provide complete, accurate, and up-to-date answers that actually work.
Related Questions
What's the best way to define custom id generation as default in Grails?
grails using uuid as id and mapping to to binary column
Configuring Grails/Hibernate/Postgres for UUID
Problems mapping UUID in JPA/hibernate
Custom 16 digit ID Generator in Grails Domain
Using UUID and RAW(16)
If you want to use a UUID in your Grails domain and a RAW(16) in your database, you'll need to add the following.
For every domain, specify the id field. Here's an example using ExampleDomain.groovy
class ExampleDomain {
UUID id
}
Add the following mapping to Config.groovy
grails.gorm.default.mapping = {
id(generator: "uuid2", type: "uuid-binary", length: 16)
}
For details on the three values I've selected, please see these links.
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#d0e5294
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/types.html#types-basic-value-uuid
How should I store a GUID in Oracle?
Add a custom dialect to your data source entry in Datasource.groovy. If you are using Hibernate 4.0.0.CR5 or higher, you can skip this step.
dataSource {
// Other configuration values removed for brevity
dialect = com.example.hibernate.dialect.BinaryAwareOracle10gDialect
}
Implement the custom dialect you referenced in step #3. Here is BinaryAwareOracle10gDialect implemented in Java. If you are using Hibernate 4.0.0.CR5 or higher, you can skip this step.
package com.example.hibernate.dialect;
import java.sql.Types;
import org.hibernate.dialect.Oracle10gDialect;
public class BinaryAwareOracle10gDialect extends Oracle10gDialect {
#Override
protected void registerLargeObjectTypeMappings() {
super.registerLargeObjectTypeMappings();
registerColumnType(Types.BINARY, 2000, "raw($l)");
registerColumnType(Types.BINARY, "long raw");
}
}
For more information about this change, please see the related Hibernate defect https://hibernate.atlassian.net/browse/HHH-6188.
Using UUID and VARCHAR2(36)
If you want to use a UUID in your Grails domain and a VARCHAR2(36) in your database, you'll need to add the following.
For every domain, specify the id field. Here's an example using ExampleDomain.groovy.
class ExampleDomain {
UUID id
}
Add the following mapping to Config.groovy
grails.gorm.default.mapping = {
id(generator: "uuid2", type: "uuid-char", length: 36)
}
For details on the three values, please see the links in step #2 from the previous section.
I think there is a easy way:
String id = UUID.randomUUID().toString()
static mapping = {
id generator:'assigned'
}

weblogic + eclipselink + 2 different thread = lazyloading don`t work

I have two threads one of them write text field to the database, another try to read this field but it can`t.
field has following anatation:
#Lob
#Column(name = "response_soap")
#Basic(fetch = FetchType.LAZY)
public String getResponseSoap() {
return responseSoap;
}
Both thread it's part of the web application. Both running on the same weblogic server.
All transaction is commited. There is field in the database.
Every time I'm creating new Entity manager.
What error do you get?
Try using a refresh, em.refresh(object)
Are you serializing the object? Since it is LAZY it will be null when you serialize it, unless you access before you serialize it. Try making it EAGER.
I believe that only
Many-to_many and One-to-many are can be set to lazyload
One-to-one, Many-to-one and Basic are all Egar
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Basic_Mappings/Lazy_Basics

Resources