Jersey web service, keep request count - java

i've a web service like this in a Jersey Java app:
#Singleton
#Path("/root")
public class MyWebService() {
private int count;
public MyWebService() {
count=0;
}
#Path("/perf/request")
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getCount() {
String out = "";
count++;
out = "Count is: " + out;
return out;
}
}
Due to the Jersey lifecycle, the class is re-instantiated every time a service is called (in spite of the "#Singleton" annotation) and then every time the count is equal to zero.
Is there a way to make this class/field static so the "count" field will not be reset?

That should totally work! According to the documentation:
In this scope there is only one instance per jax-rs application.
Singleton resource can be either annotated with #Singleton and its
class can be registered using the instance of Application. You can
also create singletons by registering singleton instances into
Application.
Did you register the class with the application?
public class MyApplication extends ResourceConfig {
/*Register JAX-RS application components.*/
public MyApplication () {
register(MyWebService.class);
}
}
Also you may be importing the wrong annotation type.

Related

How to get state of scoped component instance in Spring Boot

I'm looking for a way to take advantage of Spring's Scopes(Prototype or Request) while being able to get the state of these scoped components.
Given the following example
#RestController
#Scope("prototype")
public class FooController {
private FooService fooService;
#Autowired
public FooController(FooService fooService) {
this.fooService = fooService;
}
#RequestMapping("/foo")
public String foo() {
fooService.foo();
return "OK";
}
#RequestMapping("/foo/status")
public int fooStatus() {
return fooService.getState();
}
}
#Service
#Scope("prototype")
public class FooService
{
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
private int state;
public FooService() { }
public void foo() {
//do long work
state++;
//do long work
state++;
}
}
There is a Controller and a Service, prototyped scoped. How can I get the state of FooService.
The code above isn't working. Maybe something with scopes? status is always zero.
The scenario is to hit /foo/status endpoint and get the status value.
Yes, the answer 0 is expected. Because the spring prototype scope says that you'll get a new instance of the bean, everytime it's requested.
https://www.journaldev.com/21039/spring-bean-scopes
If you use request or prototype scope, it means that with every request new service bean is created with default State variable initialised to 0.
When you first call /foo a new bean of service is created and the State is increased to 2. Next when you call /foo/status new bean with default State 0 is created and returned. Which essentially means that state can't be shared between two requests with these bean scopes.
Remove the #scope on the service and controller it should start working fine.
You are creating a business logic component which is recreated on each HTTP request and keeps no track of status.
I guess you have 2 options:
remove the scope annotation that recreates your component on each request and change your actual logic / architecture (which is as you say not what you want),
define the status variable as static (not recommended). When 2 services run simultaneously your foo method you have to make your incrementation of status thread-save.

How to properly access application state from JAX-RS

#Path("/test")
public class MyClass {
#GET
public Response response() {
// Generating some expensive object here.
}
Right now I load the data into arrays etc inside the "response" function, but I want to do it before the query is even made. This way, I want to avoid reloading the data every time a a query is made. How do I achieve this?
This depends on your framework. Are you using the reference implementation Jersey? Jersey comes bundled with HK2 automatically. Then you could add
#Path("/test")
public class MyClass {
#Inject
private MyState stateful;
// here comes your code...
}
to your resource. Of course, you would still need to configure what to inject into this field. With HK2, you use an AbstractBinder for this purpose:
class MyBinder extends AbstractBinder {
private final MyState stateful;
public MyBinder (MyState stateful) {
this.stateful = stateful;
}
#Override
protected void configure() {
bind(stateful).to(MyState.class);
}
}
Finally, you need to add this binder on the application's setup. For this purpose, JAX-RS Application object can be queried for singletons. Simply add the required instance to the application such that it is returned by Application#getSingletons as here:
class MyJaxRSApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
return Collections.singletonSet(MyClass.class);
}
#Override
public Set<Object> getSingletons() {
return Collections.singletonSet(new MyBinder(new MyStateImpl()));
}
}
You can now run your application where MyStateImpl is always injected into MyClass.

How can I select Spring bean instance at runtime

Based on parameters passed to a method, I need to select from one of many Spring beans that are implementations of the same class, but configured with different parameters.
E.g. if user A invokes the method, I need to call dooFoo() on bean A, but if it's user B then I need to call the very same method, only on bean B.
Is there a 'Springier' way of doing this other than sticking all the beans in a map, and deriving a key from the parameters passed to my method?
We face that issue in our project, and we solve it through a Factory-Like class. The client class -the one that needed the bean at runtime- had an instance of the factory, that was injected through Spring:
#Component
public class ImTheClient{
#Autowired
private ImTheFactory factory;
public void doSomething(
Parameters parameters) throws Exception{
IWantThis theInstance = factory.getInstance(parameters);
}
}
So, the IWantThis instance depends on the runtime value of the parameters parameter. The Factory implementation goes like this:
#Component
public class ImTheFactoryImpl implements
ImTheFactory {
#Autowired
private IWantThisBadly anInstance;
#Autowired
private IAlsoWantThis anotherInstance;
#Override
public IWantThis getInstance(Parameters parameters) {
if (parameters.equals(Parameters.THIS)) {
return anInstance;
}
if (parameters.equals(Parameters.THAT)) {
return anotherInstance;
}
return null;
}
}
So, the factory instance holds reference to both of the posible values of the IWantThis class, being IWantThisBadly and IAlsoWantThis both implementations of IWantThis.
Seems like do you want a ServiceLocator using the application context as registry.
See ServiceLocatorFactoryBean support class for creating ServiceLocators mapping keys to bean names without coupling client code to Spring.
Other option is to use a naming convention or annotation based configuration.
for example, assuming that you annotate Services with #ExampleAnnotation("someId"), you can use something like the following Service Locator to retrieve them.
public class AnnotationServiceLocator implements ServiceLocator {
#Autowired
private ApplicationContext context;
private Map<String, Service> services;
public Service getService(String id) {
checkServices();
return services.get(id);
}
private void checkServices() {
if (services == null) {
services = new HashMap<String, Service>();
Map<String, Object> beans = context.getBeansWithAnnotation(ExampleAnnotation.class);
for (Object bean : beans.values()) {
ExampleAnnotation ann = bean.getClass().getAnnotation(ExampleAnnotation.class);
services.put(ann.value(), (Service) bean);
}
}
}
}
Sticking them in a map sounds fine. If it's a Spring-managed map (using util:map, or in Java config), that's better than creating it somewhere else, because then Spring owns all the object references and can manage their lifecycle properly.
If the beans (A, B) you are talking about are SessionScope its no problem at all, they will be selected correctly.
public class BusinessLogic {
private BaseClassOfBeanAandB bean;
public void methodCalledByUserAorB() {
bean.doFoo();
}
}

Spring Cache #Cacheable - not working while calling from another method of the same bean

Spring cache is not working when calling cached method from another method of the same bean.
Here is an example to explain my problem in clear way.
Configuration:
<cache:annotation-driven cache-manager="myCacheManager" />
<bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="myCache" />
</bean>
<!-- Ehcache library setup -->
<bean id="myCache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true">
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
<cache name="employeeData" maxElementsInMemory="100"/>
Cached service :
#Named("aService")
public class AService {
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = getEmployeeData(date);
...
}
}
Result :
aService.getEmployeeData(someDate);
output: Cache is not being used
aService.getEmployeeData(someDate);
output:
aService.getEmployeeEnrichedData(someDate);
output: Cache is not being used
The getEmployeeData method call uses cache employeeData in the second call as expected. But when the getEmployeeData method is called within the AService class (in getEmployeeEnrichedData), Cache is not being used.
Is this how spring cache works or am i missing something ?
I believe this is how it works. From what I remember reading, there is a proxy class generated that intercepts all requests and responds with the cached value, but 'internal' calls within the same class will not get the cached value.
From https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
Only external method calls coming in through the proxy are
intercepted. This means that self-invocation, in effect, a method
within the target object calling another method of the target object,
will not lead to an actual cache interception at runtime even if the
invoked method is marked with #Cacheable.
Since Spring 4.3 the problem could be solved using self-autowiring over #Resource annotation:
#Component
#CacheConfig(cacheNames = "SphereClientFactoryCache")
public class CacheableSphereClientFactoryImpl implements SphereClientFactory {
/**
* 1. Self-autowired reference to proxified bean of this class.
*/
#Resource
private SphereClientFactory self;
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull TenantConfig tenantConfig) {
// 2. call cached method using self-bean
return self.createSphereClient(tenantConfig.getSphereClientConfig());
}
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull SphereClientConfig clientConfig) {
return CtpClientConfigurationUtils.createSphereClient(clientConfig);
}
}
The example below is what I use to hit the proxy from within the same bean, it is similar to #mario-eis' solution, but I find it a bit more readable (maybe it's not:-). Anyway, I like to keep the #Cacheable annotations at the service level:
#Service
#Transactional(readOnly=true)
public class SettingServiceImpl implements SettingService {
#Inject
private SettingRepository settingRepository;
#Inject
private ApplicationContext applicationContext;
#Override
#Cacheable("settingsCache")
public String findValue(String name) {
Setting setting = settingRepository.findOne(name);
if(setting == null){
return null;
}
return setting.getValue();
}
#Override
public Boolean findBoolean(String name) {
String value = getSpringProxy().findValue(name);
if (value == null) {
return null;
}
return Boolean.valueOf(value);
}
/**
* Use proxy to hit cache
*/
private SettingService getSpringProxy() {
return applicationContext.getBean(SettingService.class);
}
...
See also Starting new transaction in Spring bean
Here is what I do for small projects with only marginal usage of method calls within the same class. In-code documentation is strongly advidsed, as it may look strage to colleagues. But its easy to test, simple, quick to achieve and spares me the full blown AspectJ instrumentation. However, for more heavy usage I'd advice the AspectJ solution.
#Service
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class AService {
private final AService _aService;
#Autowired
public AService(AService aService) {
_aService = aService;
}
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = _aService.getEmployeeData(date);
...
}
}
If you call a cached method from same bean it will be treated as a private method and annotations will be ignored
Yes, the caching will not happen because of the reasons that were already mentioned in the other posts. However I would solve the problem by putting that method to its own class (service in this case). With that your code will be easier to maintain/test and understand.
#Service // or #Named("aService")
public class AService {
#Autowired //or how you inject your dependencies
private EmployeeService employeeService;
public List<EmployeeData> getEmployeeData(Date date){
employeeService.getEmployeeData(date);
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = getEmployeeData(date);
...
}
}
#Service // or #Named("employeeService")
public class EmployeeService {
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
println("This will be called only once for same date");
...
}
}
In my Case I add variable :
#Autowired
private AService aService;
So I call the getEmployeeData method by using the aService
#Named("aService")
public class AService {
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = aService.getEmployeeData(date);
...
}
}
It will use the cache in this case.
Better approach should be creating another service like ACachingService and call ACachingService.cachingMethod() instead of self Autowiring ( or any other approach trying to self inject). This way you do not fall into Circular dependency, which may be resulted in warning/error when upgrade to newer Spring ( Spring 2.6.6 in my case ) :
ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'webSecurityConfig':
Requested bean is currently in creation: Is there an unresolvable circular reference?
We looked at all the solutions here and decided to use a separate class for the cached methods because Spring 5 doesn't like circular dependencies.
Use static weaving to create proxy around your bean. In this case even 'internal' methods would work correctly
I use internal inner bean (FactoryInternalCache) with real cache for this purpose:
#Component
public class CacheableClientFactoryImpl implements ClientFactory {
private final FactoryInternalCache factoryInternalCache;
#Autowired
public CacheableClientFactoryImpl(#Nonnull FactoryInternalCache factoryInternalCache) {
this.factoryInternalCache = factoryInternalCache;
}
/**
* Returns cached client instance from cache.
*/
#Override
public Client createClient(#Nonnull AggregatedConfig aggregateConfig) {
return factoryInternalCache.createClient(aggregateConfig.getClientConfig());
}
/**
* Returns cached client instance from cache.
*/
#Override
public Client createClient(#Nonnull ClientConfig clientConfig) {
return factoryInternalCache.createClient(clientConfig);
}
/**
* Spring caching feature works over AOP proxies, thus internal calls to cached methods don't work. That's why
* this internal bean is created: it "proxifies" overloaded {#code #createClient(...)} methods
* to real AOP proxified cacheable bean method {#link #createClient}.
*
* #see Spring Cache #Cacheable - not working while calling from another method of the same bean
* #see Spring cache #Cacheable method ignored when called from within the same class
*/
#EnableCaching
#CacheConfig(cacheNames = "ClientFactoryCache")
static class FactoryInternalCache {
#Cacheable(sync = true)
public Client createClient(#Nonnull ClientConfig clientConfig) {
return ClientCreationUtils.createClient(clientConfig);
}
}
}
I would like to share what I think is the easiest approach:
Autowire the controller and use to call the method it instead of using the class context this.
The updated code would look like:
#Controller
public class TestController {
#Autowired TestController self;
#RequestMapping("/test")
public String testView(){
self.expensiveMethod();
return "test";
}
#Cacheable("ones")
public void expensiveMethod(){
System.out.println("Cache is not being used");
}
}
The default advice mode for processing caching annotation is “proxy”. At the startup of an application, all the caching annotations like #Caching, #Cacheable, #CacheEvict etc. are scanned and a target proxy class is generated for all of these classes. The proxy allows for intercepting the calls to these cacheable methods, which adds the caching advice/behavior.
So when we invoke the cacheable methods from the same class, as shown below, calls from the clients don’t get intercepted in a way that allows for caching advice to be added to them. Hence, every single time there is an unexpected cache miss.
Solution: Invoke the Cacheable methods from a different bean to use proxy class with caching advice.

Loading the class only once

I am implementing an service class which uses the services of the third party providers.
User will interact with the Service class to get the service of the service provider.
My requirement:
I want to load the service class only once( or it persist for long time in memory say 2 Hr.).
My question:
How can I check that this service class is loaded only once?
If it is loaded each time an request is made so is there any way to them persist in the memory?
Here is the code of my Service class
package com.example;
import com.example.spi.Multiplication;
import java.util.Iterator;
import java.util.ServiceLoader;
public class MultiplicationService implements Multiplication{
private static MultiplicationService service;
private ServiceLoader loader;
public static int no=0;
private MultiplicationService() {
loader = ServiceLoader.load(Multiplication.class);
}
public static synchronized MultiplicationService getInstance() {
if (service == null) {
service = new MultiplicationService();
}
return service;
}
public int getMultiplication(int a,int b){
int result = 0;
try {
Iterator multiply = loader.iterator();
while (result == 0 && multiply.hasNext())
{
Multiplication d = multiply.next();
result = d.getMultiplication(a,b);
System.out.println("Result is : "+ result);
}
} catch (Exception serviceError) {
result = 0;
serviceError.printStackTrace();
}
return result;
}
}
Thanks
You can implement the singleton pattern. One option is using an enum:
public enum Service {
INSTANCE;
private ThirdPartyService service = new ThirdPartyService();
public ThirdPartyService getService() {
return service;
}
}
But don't overuse that pattern, because it makes it hard to unit-test your code.
Go for Spring.
Make a bean entry and keep it singleton [which is by default]
It will create an object of that class once when context is initialized then it won't touch the class and your purpose will get solved.
You could also check out OSGi, which has a service model and will take care of all class loading for you. You can also combine it with Spring to get the benefits from both worlds.

Categories

Resources