Is it possible to use Spring #Retryable in #Configurable classes? - spring

I would like to use Spring #Retryable annotation with #Configurable class. But it seems doesn't work. Is there any way to do it?
I have a legacy dao class which is out of Spring context (because it is used in classes out of Spring context). Some of data access calls are not reliable thus it was decided to give a try to #Retryable. Here an example:
#Configurable
public class SomeLegacyDao {
#Autowired
private JdbcTemplate jdbcTemplate;
#Retryable(value = DataAccessException.class,
maxAttempts = 2, backoff = #Backoff(delay = 100))
public int count() {
return jdbcTemplate.queryForObject(...);
}
}
I can't use #Component/#Repository right now because of the way the other code instantiates dao:
SomeLegacyDao dao = new SomeLegacyDao();

As far as I understand the life cycle of spring it is not possible. When looking into the life cycle of spring (https://howtodoinjava.com/spring-core/spring-bean-life-cycle/ ) it starts with loading the Configuration. Classes annotated with #Configuration are used to instantiate Beans. The #Retryable annotation is, as far as i know, used by the Proxys that Spring creates around beans. You therefore already require a setup Context which can not be done before the configuration is loaded.
If you provide a example/reason for your use case there might be a different approach to your Problem :)

Related

How to expose endpoints REST lazily?

Scenario:
The Spring Boot application should expose its REST endpoints
only when a specific action occurs.
Is there any way in Spring to lazily expose endpoints, or even the whole HTTP subsystem?
In Apache CXF, we can do something like this:
void exposeEndpoints() {
EndpointImpl endpoint = new EndpointImpl(cxfBus, serviceImpl);
endpoint.publish();
}
How to do the same thing in Spring?
You could take a look at #RefreshScope.
I would define my #RestController beans as follows:
#Configuration
#RefreshScope
public ControllerConfig {
#Bean
#ConditionalOnProperty(value = "should.initialize.rest", havingValue = true)
public SomeController someController(){
....
}
#Bean
#ConditionalOnProperty(value = "should.initialize.rest", havingValue = true)
public SomeOtherController someOtherController(){
....
}
}
and if you start your application with property should.initialize.rest with value false in your application.properties:
should.initialize.rest=false
Then your controllers won't be registered/initialized. When the application is running, you could then update your application.properties to:
should.initialize.rest=true
and make a call to /refresh, then your ApplicationContext will reload/refresh, this time with your REST controllers. You can find more about #RefreshScope below:
https://www.baeldung.com/spring-reloading-properties
https://andressanchezblog.wordpress.com/2016/09/15/refresh-scope-in-spring-cloud/
The solution I have provided below is one of the ways and it may or may not be suitable in your case.
It situation seems like more of design concern rather than particular implementation.
I would suggest you to go with little change in the design.
Store the event in DB or Session (as per requirement) as Boolean.
Create Aspect using AspectJ or Spring's own AOP.
Create Before aspect with specific package pointcuts.
In the #Before advice, check for the boolean flag, if the condition for publishing
satisfies than use joinpoint.proceed() else throw some kind of error saying service not available.
Another way is to create custom Annotation with Aspects. You can use that annotation as per requirement and not on the whole service layer.
The benefit of first approach is that you have the control at generic level and the second approach at service level.
I would suggest to create a new child context with your HTTP subsystem. Something like this:
#Service
public class MyBusinessService {
#Autowired
private final ApplicationContext parentContext;
private AnnotationConfigWebApplicationContext webContext;
public void myBusinessMethod() {
this.webContext = new AnnotationConfigWebApplicationContext();
this.webContext.setParent(parentContext);
this.webContext.scan("com.mybusiness.service.webcomponents");
this.webContext.refresh();
this.webContext.start();
}
}
DISCLAIMER: This is proof-of-concept code, I did not try to compile or run this. But hopefully it is enough to illustrate the concept.

Spring Proxy Creation of Classes annotated with #Configuration or #Component

Spring uses either JDK dynamic proxies or CGLIB to create the proxy for a given target object. If a class is annotated with #Configuration, then CGLIB is used.
However, one limitation of Spring AOP is that once the call has finally reached the target object, any method calls that it may make on itself are going to be invoked against the this reference, and not the proxy. This piece of information is important to remember when using #Transactional and in other places as well.
So having that knowledge, in the code below, is Spring injecting the actual instance or the proxy of SimpleBean?
#Configuration
public class Config {
#Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
#Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean()); //<---
}
}
And what is the behavior if a class is annotation with #Component?
Let me give you another perspective.
Say there is an another bean AnotherBeanConsumer that also needs a simpleBean. Simple Bean has a Singleton scope:
#Configuration
public class Config {
#Bean
public SimpleBean simpleBean() {
return new SimpleBean();
}
#Bean
public SimpleBeanConsumer simpleBeanConsumer() {
return new SimpleBeanConsumer(simpleBean());
}
#Bean
public AnotherBeanConsumer anotherBeanConsumer() {
return new AnotherBeanConsumer(simpleBean());
}
}
Now the question is, how its possible that two calls to simpleBean() made from different methods simpleBeanConsumer and anotherBeanConsumer return the same instance of the simple bean (since its a singleton obviously)?
IMO (and disclaimer, I'm not affiliated with spring or something), This is the main reason of creating proxies that wrap Configurations.
Now indeed Spring AOP has a limitation of calling methods just as you've stated, however who said that spring under-the-hood uses spring AOP? The bytecode instrumentation done on much lower levels doesn't have a limitation like this. After all creating a proxy means: "create a proxy object that will have the same interface but will alter the behavior", right?
For example if you use CGLIB that uses inheritance you could create a proxy out of configuration that looks like this (schematically):
class CGLIB_GENERATED_PROXY extends Config {
private Map<String, Object> singletonBeans;
public SimpleBean simpleBean() {
String name = getNameFromMethodNameMaybePrecached();
if(singletonBeans.get(name) != null) {
return singletonBeans.get(name);
}
else {
SimpleBean bean = super.simpleBean();
singletonBeans.put(name, bean);
return bean;
}
}
....
}
Of course its only a schematic picture, in real life there is an application context that basically provides the access to the map like this, but you get the point.
If its not enough, then there are some even more sophisticated frameworks that spring must make use of in order to load a configuration (like ASM)...
Here is an example:
If you use #ConditionalOnClass(A.class) and the class doesn't really exist in runtime, how spring can load the bytecode of the configuration that uses this configuration and not fail on something like NoClassDefFoundException?
My point is that it goes far beyond the spring AOP, and has its quirks :)
Having said that, nothing that I've describe above requires the real components to be always wrapped in Proxies of any kind. So in the most trivial case, when SimpleBean does not by itself have some annotations that require proxy generation (stuff like #Cached, #Transactional and so forth), Spring won't wrap the object of that type and you'll get a plain SimpleBean object.

Spring #Configurable with JavaConfig on GAE-Objectify classes

I have such an Objectify Entity class
#Entity
#Cache
#Index
public class DummyEntity {
#Id private Long id;
private ObjectifyStartup objectifyStartup;
private String someData;
//Getters and setters for all
}
This ObjectifyStartup is a bean initialized in Web MVC JavaConfig file which I need to be injected into any DummyEntity instance
#EnableWebMvc
#Configuration
public class SpringWebMvcConfig extends WebMvcConfigurerAdapter {
#Bean
public ObjectifyStartup objectifyStartup() { return new ObjectifyStartupImpl(); }
}
I want to do this somewhere in the code, basically in a controller
DummyEntity newDummy = new DummyEntity();
I know I need to use #Configurable annotation on the DummyEntity to make the Spring container inject the dependency, but what is the JavaConfig code I have to put into SpringWebMvcConfig class for this DI to work?
I cannot use Autowiring, Component Scans because of the performance hit in GAE due to Autowiring from best practices mentioned here Spring GAE Optimization . And all the solutions I have encountered uses #Autowired with #ComponentScan with <context:spring-configured/>. Kindly provide a solution that uses subjective declarations than autowiring.
After quite some time since I asked this question, I changed the strategy and I am now not initializing a ObjectifyStartup bean to provide me with ofy() service, as from Objectify Docs it is not advisable to create an instance of ofy() and using it pan-application. I was doing it so here because in the ObjectifyStartup bean I was registering all my Entities with the Objectify and then getting hold of its bean instantiation to do datastore operations. But now I have moved the Entities registration to a static block that executes with Spring bootstraps my application.

Spring dynamic autowire services

I've started to build some kind of a CMS and I'm stuck over one idea.
The description is:
I have standard MVC Controller (Home) in which I'm downoading modules settings which will be set in this Controller.
The response is, that I have to implement module with name "HPModule".
So I'm trying to load this module by Class.forName("com.app.something.HPModule"); and then call method init();
My HPModule is:
public class HPModule
{
#Resource(name = "hpModuleService")
private HPModuleService hpModuleService;
public String init()
{
SomeObject someObject = hpModuleService.getArticle();
}
}
And I found that when I'm trying to do SomeObject someObject = hpModuleService.getArticle(); Spring is blind for #Resource when I'm calling class by Class.forName.
How to solve this issue?
The HPModule has to be a Spring Bean retrieved by means of DI or directly from Spring BeanFactory. You cannot expect Spring to autowire a class that is not instantiated by Spring, unless You use #Configurable and AspectJ to weave the class.
If HPModule already is a Spring Bean, than just #Autowire or #Inject it directly into the MVC controller that needs it.
If You don't know in compile time what modules You'll need, than inject ListableBeanFactory and use BeanFactoryUtils to get the modules You need in runtime by type or by name.

Use Spring #Transactional in Scala

We have a mixed Java and Scala project, which uses Spring transaction management. We are using the Spring aspects to weave the files with #Transactional annotated methods.
The problem is, that the Scala classes aren't woven with the Spring transaction aspects. How can I configure Spring to regard the transaction in Scala?
Spring needs your transaction boundary to begin with Spring-managed beans, so this precludes #Transactional Scala classes.
It sounds like the simple solution is to make service facades which are #Transactional Java classes instantiated as Spring beans. These can delegate to your Scala service/core code.
A Scala-only solution is to use Eberhard Wolff's closure that creates a manual transaction. Usage:
transactional() {
// do stuff in transaction
}
https://github.com/ewolff/scala-spring/blob/master/src/main/scala/de/adesso/scalaspring/tx/TransactionManagement.scala
https://github.com/ewolff/scala-spring/blob/master/src/main/scala/de/adesso/scalaspring/tx/TransactionAttributeWithRollbackRules.scala
Found here: http://www.slideshare.net/ewolff/scala-and-spring (slide 41)
License: Apache
There is nothing special about Spring's #Transactional support in Scala and you can use it without any Java code. Just make sure that you have "pure" traits for beans, which implementations would use #Transactional annotation. You should also declare a bean with PlatformTransactionManager type (if you are using .xml-based Spring configuration, you should use "transactionManager" for bean name, see EnableTransactionManagement's JavaDoc for details). Also, if you are using annotation-based configuration classes, be sure that these classes are placed in their own dedicated files, i.e. don't place any other classes (companion object is OK) in the same file. Here is simple working example:
SomeService.scala:
trait SomeService {
def someMethod()
}
// it is safe to place impl in the same file, but still avoid doing it
class SomeServiceImpl extends SomeService {
#Transactional
def someMethod() {
// method body will be executed in transactional context
}
}
AppConfiguration.scala:
#Configuration
#EnableTransactionManagement
class AppConfiguration {
#Bean
def transactionManager(): PlatformTransactionManager = {
// bean with PlatformTransactionManager type is required
}
#Bean
def someService(): SomeService = {
// someService bean will be proxied with transaction support
new SomeServiceImpl
}
}
// companion object is OK here
object AppConfiguration {
// maybe some helper methods
}
// but DO NOT place any other trait/class/object in this file, otherwise Spring will behave incorrectly!

Resources