I try to use aspect for repeatable actions.
I have following aspect configuration:
#Aspect
#Component
public class TestInterceptor {
#Around("execution(public Map<Object, Object> controller.class.ContollerName+.*(..)) && this(self)")
public Object configureCommonResponse(ProceedingJoinPoint pjp, ControllerName self) throws Throwable {
return pjp.proceed();
}
}
Also I have a controller with methods which I need to modify:
#Controller
public class ControllerName {
#RequestMapping("/test")
public Map<Object, Object> test() {
....
}
}
However when I try to invoke test method I get following exception:
SEVERE: Servlet.service() for servlet [springServlet] in context with path [/test] threw exception [Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'controllerName': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.Integer controller.pageSize; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'className' defined in URL [jar:file:/pathToJar.jar!/className/ClassName.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class className.ClassName]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given] with root cause
Why does it try to create a subclas for ClassName class? I explicitly asked to intercept executions in controller.class.ContollerName and subclasses, did not I?
Related
I have a springboot app, in which I am connecting to cassandra DB.
My pom.xml:
parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
The cassandraConfig definitition:
#Configuration
#PropertySource("file:///Users/s1b03vf/Work/carrierhub/cass.properties")
#ConfigurationProperties()
#EnableCassandraRepositories(basePackageClasses = {MCSEDistributorRepository.class})
public class MSCECassandraConfig {
protected String contactPoints;
protected int port;
protected String username;
protected String password;
protected String keyspace;
#Override
protected AuthProvider getAuthProvider() {
return new PlainTextAuthProvider(username, password);
}
#Override
protected String getKeyspaceName() {
return keyspace;
}
#Override
protected String getContactPoints() {
return contactPoints;
}
#Override
protected int getPort() {
return port;
}
#Override
public String[] getEntityBasePackages() {
return new String[]{"com.example.demo.entity.cassandra"};
}
}
Repository class:
#Repository
public interface MCSEDistributorRepository extends CassandraRepository<MCSEDistributor, String> {
}
Entity class:
#Table("mcse_offer")
public class MCSEDistributor {
#Column
#PrimaryKey
private int id;
#Column
private String name;
}
Now when I start my application I am running into the below error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/Users/s1b03vf/.m2/repository/io/springfox/springfox-spring-web/2.9.2/springfox-spring-web-2.9.2.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/Users/s1b03vf/.m2/repository/io/springfox/springfox-spring-web/2.9.2/springfox-spring-web-2.9.2.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Unsatisfied dependency expressed through method 'requestMappingHandlerMapping' parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mvcConversionService' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.format.support.FormattingConversionService]: Factory method 'mvcConversionService' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MCSEDistributorRepository': Cannot resolve reference to bean 'cassandraTemplate' while setting bean property 'cassandraTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cassandraTemplate' defined in class path resource [com/example/demo/config/MSCECassandraConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.cassandra.core.CassandraAdminTemplate]: Factory method 'cassandraTemplate' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [com/example/demo/config/MSCECassandraConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.cassandra.SessionFactory]: Factory method 'sessionFactory' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'session' defined in class path resource [com/example/demo/config/MSCECassandraConfig.class]: Invocation of init method failed; nested exception is com.datastax.driver.core.exceptions.DriverInternalError: Unexpected exception thrown
It says dependency and bean creation issue for cassandraTemplate and sessionFactory. I am new to using spring-data, so not sure what I am missing here.
From startup log, I can see that it is using the below driver version:
2020-06-08 22:44:57.782 INFO 42129 --- [ restartedMain] com.datastax.driver.core : DataStax Java driver 3.7.2 for Apache Cassandra
Try calling super and then set the required properties
#Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = super.cluster();
cluster.setContactPoints("127.0.0.1");
cluster.setPort(9142);
return cluster;
}
Figured out the issue. Issue was that the CassandraConfig class was missing this:
#Override
protected boolean getMetricsEnabled() {
return false;
}
Added this and it started running fine.
There is something wrong with your #configuration class. it doesn't have #bean annotations. look at this example cassandra #configuration class from: https://www.baeldung.com/spring-data-cassandra-tutorial
#Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {
#Override
protected String getKeyspaceName() {
return "testKeySpace";
}
#Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster =
new CassandraClusterFactoryBean();
cluster.setContactPoints("127.0.0.1");
cluster.setPort(9142);
return cluster;
}
#Bean
public CassandraMappingContext cassandraMapping()
throws ClassNotFoundException {
return new BasicCassandraMappingContext();
}
}
There is also explanation on how to configure the repository and table.
I have #ConditionalOnProperty(value = jms.enabled) on interface that extends JpaRepository, how I can test bean creation?
I try
private final ApplicationContextRunner runner =
new ApplicationContextRunner().withConfiguration(UserConfigurations.of(SomeRepository.class));
#Test
public void shouldCreateBeanWhenJmsEnabled() {
runner.withPropertyValues("jms.enabled=true")
.run(context -> assertThat(context).hasBean("someRepository"));
}
but I get
java.lang.AssertionError:
Expecting:
<Unstarted application context org.springframework.boot.test.context.assertj.AssertableApplicationContext[startupFailure=org.springframework.beans.factory.BeanCreationException]>
to have bean named:
<"someRepository">:
but context failed to start:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someRepository': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.kek.repository.SomeRepository]: Specified class is an interface
I am trying to run a batch job, where I want to make my SQL query dynamic. But I'm getting an exception while building code as "Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?". Below are the code snippets and exception trace for the same.
BatchConfig
#Configuration
#EnableBatchProcessing
public class StoreSalesBatchConfiguration {
#Autowired
#Qualifier("jobBuilderFactory")
private JobBuilderFactory jobBuilderFactory;
#Autowired
#Qualifier("stepBuilderFactory")
private StepBuilderFactory stepBuilderFactory;
#Autowired
#Qualifier("jobCompletionNotificationListener")
private JobCompletionNotificationListener jobCompletionNotificationListener;
#Autowired
#Qualifier("jobLauncher")
private JobLauncher jobLauncher;
#Autowired
#Qualifier("storeSalesJob")
private Job storeSalesJob;
#Autowired
private GameStoreSalesRepository storeSalesRepository;
#Bean
#StepScope
ItemReader<GameStoreSales> gameStoreSalesReader(#Qualifier("gdwMpsBatch") final DataSource dataSource,
#Value("#{jobParameters[maxDate]}") String maxDate) {
JdbcCursorItemReader<GameStoreSales> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql(CommonConstants.STORE_SALES_QUERY);
databaseReader.setPreparedStatementSetter(new PreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, maxDate);
}
});
databaseReader.setRowMapper(new BeanPropertyRowMapper<>(GameStoreSales.class));
return databaseReader;
}
#Bean
public GameStoreSalesProcessor gameStoreSalesProcessor() {
return new GameStoreSalesProcessor();
}
#Bean
public ItemWriter<GameStoreSales> gameStoreSalesWriter() throws Exception {
return new GameStoreSalesWriter();
}
#Bean
public Step gameStoreSalesStep(#Qualifier("gdwMpsBatch") final DataSource dataSource,
#Value("#{jobParameters[maxDate]}") String maxDate) throws Exception {
return stepBuilderFactory.get("gameStoreSalesStep").<GameStoreSales, GameStoreSales>chunk(1000)
.reader(gameStoreSalesReader(dataSource,maxDate)).processor(gameStoreSalesProcessor()).writer(gameStoreSalesWriter()).build();
}
#Bean(name = "storeSalesJob")
public Job storeSalesJob(Step gameStoreSalesStep) {
return jobBuilderFactory.get("storeSalesJob").incrementer(new RunIdIncrementer())
.listener(jobCompletionNotificationListener).flow(gameStoreSalesStep).end().build();
}
#Scheduled(cron = "*/30 * * * * *")
public void runStoreSalesJob() throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
String dateParam = new Date().toString();
String maxDate = storeSalesRepository.getMaxCalDate();
JobParameters param = new JobParametersBuilder().addString("date", dateParam)
.addString("maxDate", weekEnd)
.toJobParameters();
try{
jobLauncher.run(storeSalesJob, param);
} catch(Exception e){
e.printStackTrace();
}
}
}
Exception Trace:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'storeSalesBatchConfiguration': Unsatisfied dependency expressed through field 'storeSalesJob'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'storeSalesJob' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'storeSalesJob' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'storeSalesJob' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'storeSalesJob' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Please suggest why jobParameters are not being recognised and where the configuration is going wrong.
A spring batch StepScope object is one which is unique to a specific step and not a singleton. As you probably know, the default bean scope in Spring is a singleton. But by specifying a spring batch component being StepScope means that Spring Batch will use the spring container to instantiate a new instance of that component for each step execution.
This is often useful for doing parameter late binding where a parameter may be specified either at the StepContext or the JobExecutionContext level and needs to be substituted for a placeholder, much like your example with the filename requirement.
Another useful reason to use StepScope is when you decide to reuse the same component in parallel steps. If the component manages any internal state, its important that it be StepScope based so that one thread does not impair the state managed by another thread (e.g, each thread of a given step has its own instance of the StepScope component).
Try annotating with StepScope:
#Bean
#StepScope
public Step gameStoreSalesStep(#Qualifier("gdwMpsBatch") final DataSource dataSource,
#Value("#{jobParameters[maxDate]}") String maxDate) throws Exception {
return stepBuilderFactory.get("gameStoreSalesStep").<GameStoreSales, GameStoreSales>chunk(1000)
.reader(gameStoreSalesReader(dataSource,maxDate)).processor(gameStoreSalesProcessor()).writer(gameStoreSalesWriter()).build();
}
Error From Console
SEVERE: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeController': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.ram.service.EmployeeService com.ram.controller.EmployeeController.employeeService;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeService': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.ram.dao.EmployeeDao com.ram.service.EmployeeServiceImpl.employeeDao;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeDao': Injection of autowired dependencies failed;
EmployeeController.java
#Controller
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#Qualifier(value="employeeService")
public void setEmployeeService(EmployeeService employeeService){
this.employeeService = employeeService;
}
#RequestMapping(value = "/employees", method = RequestMethod.GET)
public String listEmployee(Model model) {
model.addAttribute("employee", new Employee());
model.addAttribute("listEmployee", employeeService.listEmployee());
return "employee";
}
This line is most imporatant from the log. Unfortunately, the log is incomplete, so it's unclear which property of EmployeeDao is missing:
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeDao': Injection of autowired dependencies failed;
What fields are you mapping into EmployeeDao? Because one of those cannot be found, perhaps not marked with #Component?
I want to do a custom HealthIndicator that depends on the application uptime.
#Component
public class HealthActuator implements HealthIndicator {
private final MetricsEndpoint metricsEndpoint;
#Autowired
public HealthActuator(MetricsEndpoint metricsEndpoint) {
this.metricsEndpoint = metricsEndpoint;
}
#Override
public Health health() {
long uptime = (Long) metricsEndpoint.invoke().get("uptime");
// logic with uptime
return Health.up().build();
}
}
But there is an error: a circular dependency between 2 beans in the application context.
I can get uptime metric with a rest call to my endpoint /actuator/health.
But maybe is it possible to do it programmatically?
P.S. Log stacktrace:
11-01 14:34:09 WARN org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'healthActuator' defined in file [/Users/serge/projects/bb/bb-imapl/target/classes/bb/imapl/config/HealthActuator.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration$$EnhancerBySpringCGLIB$$2bb06d4a]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'healthActuator': Requested bean is currently in creation: Is there an unresolvable circular reference?
11-01 14:34:09 WARN org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'healthActuator' defined in file [/Users/serge/projects/bb/bb-imapl/target/classes/bb/imapl/config/HealthActuator.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration$$EnhancerBySpringCGLIB$$2bb06d4a]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'healthActuator': Requested bean is currently in creation: Is there an unresolvable circular reference?
11-01 14:34:09 ERROR org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
There is a circular dependency between 2 beans in the application context:
- healthActuator defined in file [/Users/serge/projects/bb/bb-imapl/target/classes/bb/imapl/config/HealthActuator.class]
- org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration
- healthActuator
11-01 14:34:09 ERROR org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter -
If you do not like setter injection, it should also be possible to work around this with #Lazy...
#Autowired
public HealthActuator(#Lazy MetricsEndpoint metricsEndpoint) {
this.metricsEndpoint = metricsEndpoint;
}
EndpointAutoConfiguration has a dependency on HealthIndicator (which you implemented with HealthActuator).
So you end up with a circular dependency. This happens when 2 beans needs each other to instantiate themselves (through constructor injection).
You can break the cycle by using a setter injection:
#Component
public class HealthActuator implements HealthIndicator {
private MetricsEndpoint metricsEndpoint;
#Autowired
private void setMetricsEndpoint(MetricsEndpoint metricsEndpoint) {
this.metricsEndpoint = metricsEndpoint;
}
public HealthActuator() {
}
#Override
public Health health() {
long uptime = (Long) metricsEndpoint.invoke().get("uptime");
// logic with uptime
return Health.up().build();
}
}