Guice: How can I cache data - java

I am new to Guice and have a question regarding caching.
I have a WebApp which uses a provider to provide user configurations.
bind(UserConfiguration.class).toProvider(UserConfigurationProvider.class).in(ServletScopes.REQUEST);
The provider is declared as:
public class UserConfigurationProvider implements Provider<UserConfiguration>{
public UserConfiguration get() {
userConfigurationDatabase.getUserConfiguration(<some param here>);
}
}
In the get method, it calls DB and make a very expensive DB call.
I have a number of classes which get UserConfiguration injected like:
public class PriceView {
private UserConfiguration userConfiguration;
#Inject
public MyClass(UserConguration userConfiguration){
this.userConfiguration = userConfiguration;
}
.....
}
public class OrderView {
private UserConfiguration userConfiguration;
#Inject
public MyClass(UserConguration userConfiguration){
this.userConfiguration = userConfiguration;
}
........
}
The problem is that every time I switch a view, a new xxxxView object is created and hence a new UserConfiguration is injected and hence the expensive DB call is called.
I want to make calling the DB limited to once per user login. My idea is that cache the UserConfiguration somewhere when a user login and clear it after user logout or it expires.
But I want to know whehter Guice offers something more clever ways of caching about this use case?
Many thanks.

If you're using standard servlet session, then it should be enough to use ServletScopes.SESSION scope instead of ServletScopes.REQUEST. In this case the injected object should be created only once per session.
However, if you are not using standard servlet session but something custom, then you also need to create custom scope.

Related

How to access object without passing it as parameter?

Is there a way to autowire an object that needs to be re-instantiated frequently?
I am using Netflix's DGS + spring boot framework, and basically storing the user authentication details in a custom context which is created for each request. I am trying to avoid adding context to the method signature because of the large amount of refactoring needed.
e.g.
public Result dataFetcher(DataFetchingEnvironment dfe) {
// this context contains user details which is used for authorization
// instantiated for every request
setRolesInContext(dfe);
MyCustomContext context = DgsContext.getCustomContext(dfe);
// trying to avoid adding context as an extra param e.g. dataFetcherHelper(context)
dataFetcherHelper(); // this calls other helper methods from other classes
}
I was thinking of using the facade pattern but this would not be thread safe. Basically autowire the RequestContextHolder, and call setRequestContext each time a new context gets initialized.
#Component
#NoArgsConstructor
#Getter
#Setter
public class RequestContextHolder {
private RequestContext requestContext;
}
I'm not sure how your question:
Is there a way to autowire an object that needs to be re-instantiated frequently?
Is related to the use case that you've presented in the question...
From the question it looks like you can consider using ThreadLocals as a conceptual "substitution" to the global variable available all over the place in the request if you don't want to add parameters to the methods to propagate the context through the flow.
This will work only in "thread-per-request" model, it won't work for reactive systems and for the complicated cases where you maintain different thread pools and switch the threads while implementing the Business Logic on backend:
So to achieve "thread-safety" in your context holder that you have suggested you can use:
#Configuration
public class MyConfig {
#Bean
public ThreadLocal<MyCustomContext> ctxHolder() {
return new ThreadLocal<>();
}
}
Then, again, if you're working in thread-per-request model, you can:
#Component
public class DataFetcherInterceptor {
#Autowired
private ThreadLocal<MyCustomContext> ctxHolder;
public Result dataFetcher(DataFetchingEnvironment dfe) {
// this context contains user details which is used for authorization
// instantiated for every request
setRolesInContext(dfe);
MyCustomContext context = DgsContext.getCustomContext(dfe);
ctxHolder.set(context);
dataFetcherHelper();
}
}
In the dataFetcherHelper or in general in any method that requires the access to the context you can:
public class SomeService {
#Autowired ThreadLocal<MyCustomContext> ctxHolder;
public void dataFetcherHelper() {
MyCustomContext ctx = ctxHolder.get();
}
Now, I see that dataFetcherHelper is just a method that you call from withing this "interceptor" class, in this case its an overkill, but I assume, you've intended that this is actually a method that belongs to another class, that might be an element in the call-chain of different classes. For these situations, this can be a working solution.

Facing issue with Guava Cache

I'm using Google Guava Cache + Spring cache abstraction for caching purpose.
I'm trying to make use of Guava's Loading Cache interface for the same.
I know Spring provides support for Guava Cache, but I was wondering whether I can make use of spring's cacheable annotation alongwith Loading Cache?
Basically I wanted to keep the business layer separate from the Cache.
Kindly help. Thanks.
Guava Cache is deprecated. If you'd existing code, that'd be another matter, but for new code, use Caffeine.
Put a #Cacheable("myCacheName") on the method that you want to cache the return value for.
Put a #EnableCaching on your application class if using Spring Boot, otherwise on some #Configuration class.
Set the spec in application.properties if using Spring Boot, like so: spring.cache.caffeine.spec=maximumSize=10000,expireAfterWrite=5m. If not using Boot, use #PropertySources annotation on the same class as in #3 above.
Add org.springframework.boot:spring-boot-starter-cache and com.github.ben-manes.caffeine:caffeine to your build file. If not using Boot, you'll need to set up the dependencies differently.
You're done.
So you want both butter and jam. Okay. I will help you use loading cache along with keeping caching logic separate.
Consider you have a service class SampleServiceImpl which implements SampleService interface.
Service interface:
public interface SampleService {
User getUser(int id);
}
Service Implementation:
#Service
public class SampleServiceImpl implements SampleService {
public User getUser(int id) {
// fetch user from database
return user;
}
}
Create one more class SampleServiceCache
public class SampleServiceCache extends ServiceCacheImpl {
#Autowired
public SampleServiceCache(int expiryTime, int maximumSize) {
loadingCache =
CacheBuilder.newBuilder().maximumSize(maximumSize).expireAfterAccess(expiryTime, TimeUnit.HOURS).build(
new CacheLoader<Integer, User>() {
#Override
public User load(#Nonnull Integer userId) {
return SampleServiceCache.super.getUser(userId);
}
});
}
#Override
public User getUser(int userId) {
return loadingCache.getUnchecked(userId);
}
}
In you bean config:
#Bean
public SampleService sampleService() {
return new SampleServiceCache(expiry, maxSize);
}
The day you want to remove cache, you have to do two things:
1. Remove the cache class.
2. Change bean config to return actual implementation object rather than cache implementation object.
P.S. You can define multiple loading caches for different behaviors say user retrieval, article retrieval, etc.

How do you handle objects created at runtime in conjunction with Dependency Injection frameworks?

I love dependency injection frameworks and how they allow me to request the one object everything starts with. All the wiring is made on the first request for that "master" object.
However, there are objects that should be created during runtime, e.g. based on user input. And sometimes those newly created objects should be shared among other objects created by the framework.
My current approach is to have "uninitialized" objects injected by the framework. During runtime I set up the object with setter methods as soon as possible.
What I don't like with this approach is that the setter methods are really invoked only once and should then never be touched again. This prevents me from declaring the fields as final. I don't now how to create the object not before all necessary information is available without losing all the benefits from the DI framework.
I'm new to DI. Are there any good patterns for this?
Example:
// The service is used through out the application
interface Service {
makeRequest()
}
What I want to do after user typed in credentials:
new ConcreteService(username, password)
// but now I need to inject the concrete servive manually everywhere I need it!
What I'm currently doing:
interface Service {
makeRequest()
setCredentials(username, password)
}
// service can be injected by framework, but I don't like setter methods
// that much (and they can pollute the interface)
Most of my experience with dependency injection is with C# but I believe the concept remains the same no matter what language.
What I understand from the original poster is that he's trying to "persist" information within the dependency injection container in order to retrieve the information at a later time.
The problem with this approach is that, in a multi-threaded scenario, there's the possibility that the dependency that you are using to persist information has its values overwritten by another thread. This can happen because the dependency injection container usually holds a single instance of the object which is returned to you whenever you need it. Therefore, you need to make sure that your design is thread safe.
In my experience, using the dependency injection container to maintain state is bad.
What you register in your dependency injection container are the objects that provide a "service" and that don't maintain any state.
Objects that you use to hold information are usually business objects. These business objects should just be instantiated with "new" (without the dependency injection container), populate them in the usual manner (with setters or initialization method or constructor) and just be passed on as part of the signature of the operations that your services expose.
Note: You can register your dependency as "transient" which would tell the dependency injection container to return a new instance every time you ask for the dependency. This would avoid the need to use the "new" keyword explicitly and give you more control when writing unit tests with a mocking framework.
Hope this helps!
One way you could do it would be to use a factory.
For example, say you had this class...
public class UserBean {
private int userId;
private UserService userService;
// other resources / dependency fields etc
public UserBean(int userId, UserService userService, ...other dependencies...) {
this.userService = userService;
this.userId = userId;
this.... = ...
}
// ...getter for userId maybe etc...
// Some method that uses the user's data AND the component/service you want to inject from Spring...
public void incrementHitCount() {
userService.incrementHitCount(userId);
}
}
...where "userService" is something you want that is managed by the IoC container. If you then have a component that needs to create one of these, e.g....
#Component
public class UserHitCountIncrementerThing {
public ResponseBean doThatThing(HttpServletRequest request) {
int userId = request.<get the user Id from it...>
UserBean userbean = new UserBean(userId, /* need dependencies here! */);
...do stuff...
}
}
You could just #Autowire in all of the services to this bean, or you could create a factory and just #Autowire one, for example...
#Component
public class UserBeanFactory {
#Autowired
private UserService userService
//...other #Autowired dependencies...
public UserBean createUser(int userId) {
return new UserBean(userService, ...etc..., userId);
}
}
Now just use this where you need it, e.g...
#Component
public class UserHitCountIncrementerThing {
#Autowired
private UserBeanFactory userFactory;
public ResponseBean doThatThing(HttpServletRequest request) {
int userId = request.<get the user Id from it...>
UserBean userbean = userFactory.createUser(userId);
...do stuff...
}
}
Is this what you were getting at?
Hope this helps.

HK2 and Impls with constructor arguments

I'm using HK2 as part of a Jersey RESTful API. I'm working in an multitenant system, and in most of my API calls, the tenant is a path parameter. I also have several DAOs, which currently accept the tenantId in their constructor, such as:
public final class WidgetMapper {
public WidgetMapper(final int tenantId) { .. }
..
}
I'd like to use HK2 to provide my DAOs to the other layers of my application. What's the right way to do this?
Change the DAOs to use a setter rather than a constructor argument. Only .. ick. The tenantId is part of the required state of the DAO.
Add a layer of abstraction. Create <interface>MapperFactory and MapperFactoryImpl, which has a no-arg constructor and a bunch of getters, such as getWidgetMapper and getGizmoMapper. Only .. this seems cumbersome. I'd rather not have to maintain these extra classes.
Is there some magic way for HK2 to inject that int value into the WidgetMapper constructor at runtime? Then I could inject the tenantId into the mapper, and the mapper into my other classes.
?? Other HK2 magic?
You need to extract the tenant ID from the path parameter in the request, so as long as it's OK to instantiate your DAOs for each request, you can implement a Factory.
public WidgetMapperFactory implements Factory<WidgetMapper> {
private final ContainerRequestContext containerRequestContext;
#Inject
public WidgetMapperFactory(ContainerRequestContext containerRequestContext) {
this.containerRequestContext = containerRequestContext;
}
public WidgetMapper provide() {
UriInfo uriInfo = containerRequestContext.getUriInfo();
List<String> matchedUris = uriInfo.getMatchedURIs();
int tenantId = 1; // Actually work it out from the matched URIs
return new WidgetMapper(tenantId);
}
public void dispose() {
// Do any clean up you need
}
}
Then bind the factory:
public MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(WidgetMapperFactory.class).to(WidgetMapper.class).in(RequestScoped.class);
}
});
}
}
You can then inject WidgetMapper in a Resource class, and the WidgetMapper doesn't have any knowledge it's being used in a web service.
Change the DAOs to use a setter rather than a constructor argument.
Only .. ick. The tenantId is part of the required state of the DAO.
If your DAOs are singletons I don't see how this would work (or at least how it could be done cleanly).
What's the right way to do this?
IMO, I think the best approach is to have 1) singleton DAOs 2) some type of proxy that got injected into the DAOs when they were instantiated by HK2 and then provided the correct tenant id for the current thread.
I can think of two ways to do this:
Option 1:
I haven't tried it, but I think you could probably inject UriInfo into your DAOs, either through the constructor, a private field, or setter. You could extract the tenant id for the current request from the UriInfo instance.
If I were you, I'd create an abstract class for my DAOs that got a UriInfo injected into a private field. I'd then provide a protected method to return the current tenant id from uriInfo.getPathParameters
public abstract class AbstractDao {
// jersey/hk2 provides a proxy that references the current thread-bound request
#Context
private UriInfo info;
protected int getTenantId()
{
// always returns the tenant id for the current request. TODO: add
// logic to handle calls that don't have a tenant id.
return Integer.valueOf(info.getPathParameters.getFirst("tenantId");
}
}
Option 2:
?? Other HK2 magic?
You could write a custom injection resolver.
One more idea...
Option 3:
This one doesn't directly answer your question since it doesn't use HK2 to inject the tenant ID into the DAOs but I think it's worth mentioning.
You could implement your own ContainerRequestFilter that obtained the tenant id and provided it to other components in your app.
By default, Jersey will invoke the filter after it resolves the resource method but before the method is actually invoked. You can obtain a UriInfo from the ContainerRequestContext, get the tenant id path param, then stuff that param into your own thread local variable. You could then reference the thread local within your DAO. Again, I recommend adding a protected method in a base DAO class to encapsulate this logic.
in most of my API calls, the tenant is a path parameter
Optionally, you can use NameBinding to control the behavior described above.
If you wanted to, you could implement option 3 using a regular ServletFilter instead.
Note:
After I wrote this answer, I realized that I assumed you were comfortable extending ResourceConfig, that you knew how to obtain an instance of ServiceLocator, and that you were comfortable with adding your own bindings. If you're not, let me know and I'll edit my answer to provide more details.

how to implement a service layer in servlet application

Suppose I want to create a service layer for my web application which uses servlets,How should I go about this?(I am not using a web app framework..So,please bear with me).Should I implement it as a listener?The service is meant to do database access.That is,I should be able to call from my servlet
class MyServlet{
...
doPost(...){
...
MyEntity entity = dbAccessService.getMyEntity(someId);
...
}
}
Where the dbAccessService should deal with hibernate session,transactions etc.Previously I used to do all this inside dao methods, but I was advised that was not a good idea.
Any suggestions welcome
thanks
mark
Sample code snippet is given below
class DBAccessServiceImpl{
...
private MyEntity getMyEntity(Long id){
Transaction tx = null;
MyEntity me = null;
Session session = HibernateUtil.getCurrentSession();
try{
tx = session.beginTransaction();
return entitydao.findEntityById(id);
}catch(RuntimeException e){
logger.info("problem occurred while calling findEntityById()");
throw e;
}
}
...
}
Then create a listener to instantiate DBAccessService
class MyAppListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent ctxEvent) {
ServletContext sc = ctxEvent.getServletContext();
DBAccessService dbservice = new DBAccessServiceImpl();
sc.setAttribute("dbAccessService",dbservice);
}
}
In web.xml add listener
...
<listener>
<listener-class>myapp.listeners.MyAppListener</listener-class>
</listener>
...
Assuming you do not want to introduce a framework, two options make sense (in my opinion):
define your service layer using stateless EJB session beans. You need an EJB container.
do it as always in OO languages, create an interface and a corresponding implementation:
Define an interface
public interface BusinessService {
abstract public BusinessObject performSomeOperation(SomeInput input);
}
And an implementation
public class BusinessServiceImpl implements BusinessService {
public BusinessObject performSomeOperation(SomeInput input) {
// some logic here...
}
}
You have several options for instantiating the service. If you start from scratch with a small application it may be sufficient to simply instantiate the service inside your web application:
BusinessService service = new BusinessServiceImpl();
service.performSomeOperation(...);
BTW: At a later time you may want to refactor and implement some abstractions around the Service instantiation (Factory pattern, dependency injection, etc.). Furthermore, in large systems there is a chance that you have to host the service layer on it's own infrastructure for scalability, so that your webapp communicates with the service layer via an open protocol, be it RESTful or Web Services.
However the future looks like, having a well defined interface defining your business functions in place, allows you to "easily" move forward if the application grows.
Response to your update:
I would not implement the service itself as a listener, this does not make sense. Nevertheless, your sample code seems to be reasonable, but you must distinguish between the Service (in this case DBAccessService) and the way you instantiate/retrieve it (the listener). The listener you've implemented plays in fact the role of a ServiceLocator which is capable of finding a certain services. If you store the instance of your Service in the servlet context you have to remind that the service implementation must be thread safe.
You have to be carefull to not over-engineer your design - keep it simple as long as you cannot foresee further, complex requirements. If it's not yet complex I suggest to encapsulate the implementation using a simple static factory method:
public final class ServiceFactory {
public static DBAccessService getDBAccessService() {
DBAccessService service = new DBAccessServiceImpl();
return service;
}
}
Complex alternatives are available to implement the ServiceFactory and nowadays some call it anti-pattern. But as long as you do not want to start with dependency injection (etc.) this one is still a valid solution. The service implementation DBAccessServiceImpl is accessed at one place only (the factory). As I mentioned before - keep an eye on multi-threading... hope this helps!
What you're suggesting is really no different to doing the session and transaction handling in a DAO. After all, your service class calls the DAO; to the client code, there is no difference.
Rather, i suspect that whoever told you not to put the session handling in the DAO was thinking that you should instead use Open Session In View pattern. Very simply, in its usual form, that involves writing a Filter which opens a session and starts a transaction before passing the request down the chain, and then commits the transaction (or rolls it back if necessary) and closes the session after the request completes. That means that within any one request, all access to persistent objects happens in a single transaction and a single session, which is usually the right way to do it (it's certainly the fastest way to do it).

Categories

Resources