Spring #Scheduled Annotation for Inherited Classes - spring

I am trying to use #Scheduled annotation for a service layer class. The class also gets monitored by a logging service through AOP.
When I make the service class implement an interface, Spring throws the error
Error creating bean with name 'dummyService' defined in file
......
......
Caused by: java.lang.IllegalStateException: failed to prepare task
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor$1.doWith(ScheduledAnnotationBeanPostProcessor.java:114)
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:452)
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:430)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:98)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1426)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
... 11 more
Caused by: java.lang.NoSuchMethodException: $Proxy23.run()
at java.lang.Class.getMethod(Class.java:1605)
at org.springframework.util.MethodInvoker.prepare(MethodInvoker.java:178)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor$1.doWith(ScheduledAnnotationBeanPostProcessor.java:111)
... 17 more
This is the service layer class:
package com.mydomain.web.myapp.service;
#Service
public class DummyService implements DummyI{
#Scheduled(cron = "${some.cron.time}")
public void run() {
}
}
If I remove the inheritance, it works without problem. Why is that?
This is what I have for the logging service :
#Component
#Aspect
public class LoggingServiceImpl implements LoggingService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
#Around("execution(* com.mydomain.web.myapp..*.*(..))")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
.....

You have several options here:
Add run() to DummyI interface
Create another interface having only run() method (or use java.lang.Runnable) and implemented that interface as well:
public class DummyService implements DummyI, Runnable
Enable class based (cglib) proxies

Related

How to resolve spring bean unavailable error?

While running my launcher class i am getting the below error
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'roles' available
My RoleLauncher Class
// reads spring config java class
package come.rahul.spring.launcher;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(RolesConfig.class);
Roles roles = context.getBean("roles", Roles.class);
My RolesConfig.class is just annotated with #Configuration and #ComponentScan("com.rahul.spring"). Its in the
package come.rahul.spring.configuartion;
My Roles Class is
package come.rahul.spring.entity;
#Component
public class Roles {
private Long roleId;
private String roleName;
//getter and setter omitted for brevity
I have one Dao and it's implementaion too
package come.rahul.spring.dao;
public interface RolesDao
{
//List<Roles> getRoles(); omitted for brevity
void print() ;
}
Its implementation is below :
package come.rahul.spring.dao;
#Repository
public class RolesDaoImpl implements RolesDao
public void print() {
System.out.println( " Inside Print method of RolesDaoImpl");
}
}
You use #ComponentScan("com.rahul.spring") but everywhere, you use package come.rahul.spring;. You need to use com everywhere instead of come

#Profile Spring Annotation in Camel

I have a Spring Boot + Apache Camel project that works brilliantly. I just added a new bean though where I wanted to have its implementation be profile-specific. I created Spring tests to verify it, and it works as expected, but when I run the server I get the following stack trace:
Caused by: org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: MyFancyBean
at org.apache.camel.component.bean.RegistryBean.getBean(RegistryBean.java:94)
at org.apache.camel.model.language.MethodCallExpression.createExpression(MethodCallExpression.java:196)
at org.apache.camel.model.language.MethodCallExpression.createPredicate(MethodCallExpression.java:210)
at org.apache.camel.model.language.ExpressionDefinition.createPredicate(ExpressionDefinition.java:148)
at org.apache.camel.model.ValidateDefinition.createProcessor(ValidateDefinition.java:63)
at org.apache.camel.model.ValidateDefinition.createProcessor(ValidateDefinition.java:35)
at org.apache.camel.model.ProcessorDefinition.makeProcessorImpl(ProcessorDefinition.java:545)
at org.apache.camel.model.ProcessorDefinition.makeProcessor(ProcessorDefinition.java:506)
at org.apache.camel.model.ProcessorDefinition.addRoutes(ProcessorDefinition.java:222)
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:1068)
I have an interface and two implementations:
public interface MyFancyBean { ... }
public class FooFancyBean implements MyFancyBean { ... }
public class NonFooFancyBean implements MyFancyBean { ... }
Depending on profile, the correct bean is read instantiated:
#Configuration
public class AppConfig {
#Bean
#Profile("foo")
MyFancyBean fooBean() {
return new FooFancyBean();
}
#Bean
#Profile("!foo")
MyFancyBean nonFooBean() {
return new NonFooFancyBean();
}
}
I've verified this works a couple of ways. First, a couple tests:
#ActiveProfiles("anything-but-foo")
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(basePackages = {"com.example", "com.jtv.spring.boot"})
#EnableAutoConfiguration
#Component
public class NonFooBean_SpringTest {
#Autowired
private MyFancyBean bean;
#Test
// ... here "bean" is instantiated as "NonFooFancyBean"
So the test works.
Further, when I start my app, depending on profile the correct bean in my #Configuration class above is called.
But Camel is still angry and says "NoSuchBeanException" on startup.
FWIW, here's how I'm referencing the bean:
#Component
public class MyCamelRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
// [...]
from("direct:processStuff").
validate().method("MyFancyBean").
process("MyProcessor");
}
}
How do I get Camel to honor this config?
Whoooo... Y'all get to be my rubber duck today. I just autowired it. (This doesn't work for my processor, which is why it didn't occur to me initially.)
#Component
public class MyCamelRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
// [...]
#Autowired MyFancyBean myFancyBean;
from("direct:processStuff").
validate().method(myFancyBean).
process("MyProcessor");
}
}

spring test fails on mockServletContext unsupportedOperation

I have a set of Integration Tests running for my Spring-Boot 1.3 app. But I had to add the following to get my maximum sessions working:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ServletContextAware {
...
#Override
public void setServletContext(ServletContext servletContext) {
servletContext.getSessionCookieConfig().setHttpOnly(true);
// causes an ApplicationEvent to be published to the Spring ApplicationContext every time a HttpSession commences or terminates
servletContext.addListener(new HttpSessionEventPublisher());
}
...
}
Now when I run my tests, I get the following:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig' defined in file [/Users/davidclark/projects/edmtotal/build/classes/main/com/edelweissco/dental/configuration/WebSecurityConfig.class]: Initialization of bean failed; nested exception is java.lang.UnsupportedOperationException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
...
Caused by: java.lang.UnsupportedOperationException
at org.springframework.mock.web.MockServletContext.addListener(MockServletContext.java:675)
at com.edelweissco.dental.configuration.WebSecurityConfig.setServletContext(WebSecurityConfig.java:123)
...
Here is an example test class (but they all fall with the same exception):
#Transactional
public class ConfigurationSettingsTest extends BaseSpecification {
#Autowired
private ConfigurationSettings configurationSettings;
#Autowired
ConfigurableApplicationContext context
...
}
where BaseSpecification is:
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
public class BaseSpecification extends Specification {
#Value('${local.server.port}')
private int serverPort;
def setup() {
RestAssured.port = serverPort;
}
}
It would seem that now when I run my integration tests, a MockServlet is being applied here, and it doesn't support. this feature. When debugging, I see that a SpringBootMockServletContext is trying to be set in setServletContext, and that is where the exception is.
I will post my answer in case anyone else runs into this. The problem was in my BaseSpecification. I added the #WebAppConfiguration and #IntegrationTest to it, and removed #IntegrationTest off the individual integration tests. Apparently this will actually create the ServletContext the way it should be.
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
#IntegrationTest
public class BaseSpecification extends Specification {

AOP applied to all public methods gives BeanCreationException exception

I have created a simple aspect that is applicable to all public methods like this:
#Aspect
#Component
public class MyAspect {
#Pointcut("execution(public * *(..))")
private void anyPublicOperation() {
}
#Before("anyPublicOperation()")
private void beforePointCut(){
System.out.println("Inside before pointcut of MyAspect");
}
}
I have below Java configuration:
#Configuration
//Enable AspectJ auto proxying
#EnableAspectJAutoProxy
#ComponentScan(basePackages={"com.examples"})
public class Config {
//Declare a bean
#Bean
public MyAspect myAspectProgram() {
return new MyAspect();
}
}
I am getting below exception when I load my configuration using AnnotationConfigApplicationContext class:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'myAspectProgram': Requested bean is currently in creation: Is there an unresolvable circular reference?
If I change the pointcut expression then I don't get any exceptions, program is working fine.
Why I am getting issue when I have the pointcut expression as #Pointcut("execution(public * *(..))")?

Injection into generic parametrized property in Spring

What is the best workaround for injection into generic parametrized property?
Simple example from record in Spring Jira:
#Component
public abstract class AbstractFoo<V extends Bar> {
#Autowired
protected V bar;
}
#Component
public ConcreteFoo1 extends AbstractFoo<ConcreteBar1> {
}
#Component
public ConcreteFoo2 extends AbstractFoo<ConcreteBar2> {
}
When I have such abstract AbstractFoo class and try to determine Spring bean which should be injected through generecis (ConcreteFoo1, ConcreteFoo1) Spring throws exception such as:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'foo.ConcreteFoo1'
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [bar.Bar] is defined:
expected single matching bean but found 2: [concreteBar1, concreteBar2]
I tested similar scenarion in Spring 3.2.1.
What is the best workaround for this problem?
This problem was reported at 10/Mar/09.
Why is this functionality still not implemented in Spring? Are there any complications preventing from solving this insufficiency?
It is like if you wrote:
#Autowired
protected Bar bar;
Spring just can't understand that you want to inject ConcreteBar1
So, you can use setter injection:
public abstract class AbstractFoo<V extends Bar> {
protected V bar;
}
#Component
public class ConcreteFoo1 extends AbstractFoo<ConcreteBar1>{
#Inject
private void setBar(ConcreteBar1 bar){
this.bar = bar;
}
}

Resources