unable to autowire TemplateEngine in thymeleaf? - java

This is my code which I use to send a html email using java spring and thymeleaf template engine.
#Service
public class EmailServiceImpl implements EmailService {
private static final String EMAIL_SIMPLE_TEMPLATE_NAME = "html/html";
#Value("${email.user.register.body}")
private String USER_REGISTER_MESSAGE_BODY;
#Value("${email.user.register.subject}")
private String USER_REGISTER_MESSAGE_SUBJECT;
#Value("${mailSender.address}")
private String SENDER_EMAIL_ADDRESS;
#Autowired
private JavaMailSender mailSender;
#Autowired
private TemplateEngine templateEngine;
#Override
public void sendEmail(MimeMessagePreparator preparator) {
mailSender.send(preparator);
}
#Async
#Override
public void sendUserRegisterEmail(String receiver, String receiverEmailAddress){
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setSubject(USER_REGISTER_MESSAGE_SUBJECT);
message.setTo(receiverEmailAddress);
message.setFrom(SENDER_EMAIL_ADDRESS);
message.setText(String.format(USER_REGISTER_MESSAGE_BODY, receiver));
}
};
sendEmail(preparator);
}
public void sendMailWithInline(
final String recipientName, final String recipientEmail, final String imageResourceName,
final byte[] imageBytes, final String imageContentType, final Locale locale)
throws MessagingException {
// Prepare the evaluation context
final Context ctx = new Context(locale);
ctx.setVariable("name", recipientName);
ctx.setVariable("subscriptionDate", new Date());
ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music"));
ctx.setVariable("imageResourceName", imageResourceName); // so that we can reference it from HTML
// Prepare message using a Spring helper
final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
final MimeMessageHelper message =
new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
message.setSubject("Example HTML email with inline image");
message.setFrom("adbuylk#gmail.com");
message.setTo(recipientEmail);
// Create the HTML body using Thymeleaf
final String htmlContent = this.templateEngine.process(EMAIL_SIMPLE_TEMPLATE_NAME, ctx);
message.setText(htmlContent, true); // true = isHtml
// Add the inline image, referenced from the HTML code as "cid:${imageResourceName}"
final InputStreamSource imageSource = new ByteArrayResource(imageBytes);
message.addInline(imageResourceName, imageSource, imageContentType);
// Send mail
this.mailSender.send(mimeMessage);
}
I am getting the following error while trying to run it using Jetty and Intellij idea.
[WARNING] Failed startup of context o.e.j.m.p.JettyWebAppContext#23321be7{/adsops,file:///E:/Projects/ADpost/ops/dev/src/main/webapp/,STARTING}{file:///E:/Projects/ADpost/ops/dev/src/main/webapp/}
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfiguration': Unsatisfied dependency expressed through field 'userDetailsService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'applicationUserServiceImpl': Unsatisfied dependency expressed through field 'emailService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'emailServiceImpl': Unsatisfied dependency expressed through field 'templateEngine'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'templateEngine' defined in com.vlclabs.adsops.configuration.WebApplicationConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.thymeleaf.spring4.SpringTemplateEngine]: Factory method 'templateEngine' threw exception; nested exception is java.lang.NoClassDefFoundError: org/thymeleaf/dialect/IExpressionEnhancingDialect
These are the dependencies
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>${thymeleaf.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-conditionalcomments</artifactId>
<version>${thymeleaf-extras-conditionalcomments.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>${thymeleaf-extras-java8time.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>${thymeleaf-extras-springsecurity4.version}</version>
</dependency>
While trying to go through the error message I understand the error may occur due to mistake I did while adding template engine. However I couldn't fix it trying for days. Please help

The problem is likely that you mix versions that are not compatible. You can check your versions by running:
mvn dependency:tree
(If you have Eclipse, you can open the pom file and switch to "Dependency Hierarchy" tab for the same thing.)
Especially check for these:
org.thymeleaf:thymeleaf-spring4:jar
org.thymeleaf:thymeleaf:jar
These two should have the same version. If they don't, adjust your dependencies.

Related

Spring batch : Error creating bean with name , Gradle, Mongodb

My Application will not start. gives me an error creating a bean with the name of my file. I've searched and found similar posts to this question but they didnt seem to pertain to my error so I am hoping someone can find what may be causing this file to fail. Also, I am at a cross between two methods. Do I use the FlatFileReader or MomgoItemreader? I just need to retrieve two things from the DB firstname and lastname. I need to read the db and then write it to a file which I havent done yet. Any help would be greatly appreciated.
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Here is my class
#Configuration
#EnableBatchProcessing
public class PaymentPortalJob {
private static final Logger LOG =
LoggerFactory.getLogger(PaymentPortalJob.class);
#SuppressWarnings("unused")
#Autowired
private JobBuilderFactory jobBuilderFactory;
#SuppressWarnings("unused")
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
private PaymentAuditRepository paymentAuditRepository;
// #Bean
// public FlatFileItemReader<PaymentAudit> PaymentPortalReader() {
// LOG.info("Inside PaymentPortalReader Method {}", "");
// return new FlatFileItemReaderBuilder<PaymentAudit>
().name("PaymentPortalReader")
// .delimited().names(new String[] { "rxFname", "rxLname" })
// .fieldSetMapper(new BeanWrapperFieldSetMapper<PaymentAudit>
() {
// {
// setTargetType(PaymentAudit.class);
// }
// }).build();
//
// }
#Bean
public ItemReader<PaymentAudit> reader() {
LOG.info("inside of ItemReader");
MongoItemReader<PaymentAudit> reader = new MongoItemReader<PaymentAudit>();
try {
reader.setTemplate(mongoTemplate());
} catch (Exception e) {
LOG.error(e.toString());
}
reader.setCollection("local");
return reader();
}
#Bean
public ItemProcessor<PaymentAudit, PaymentAudit> processor() {
return new PaymentPortalNOSQLProcessor();
}
#Bean
public ItemWriter<PaymentAudit> writer() {
MongoItemWriter<PaymentAudit> writer = new MongoItemWriter<PaymentAudit>();
try {
writer.setTemplate(mongoTemplate());
} catch (Exception e) {
LOG.error(e.toString());
}
writer.setCollection("paymentPortal");
return writer;
}
#Bean
Job job(JobBuilderFactory jbf, StepBuilderFactory sbf, ItemReader<? extends PaymentAudit> ir,
ItemWriter<? super PaymentAudit> iw) {
Step s1 = sbf.get("file-db").<PaymentAudit, PaymentAudit>chunk(100).reader(ir).writer(iw).build();
return jbf.get("etl").incrementer(new RunIdIncrementer()).start(s1).build();
}
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(new MongoClient(), "local");
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
return mongoTemplate;
}
}
appplication.yml
mongodb:
databasePort: xxxxx
databaseName: local
spring:
data:
mongodb:
host: localhost
port: xxxxx
profiles:
active: local
batch:
job:
enabled: true
Processor:
package com.spring_batchjob.job.item;
import org.springframework.batch.item.ItemProcessor;
import com.spring_batchjob.bean.PaymentAudit;
public class PaymentPortalNOSQLProcessor implements
ItemProcessor<PaymentAudit, PaymentAudit> {
#Override
public PaymentAudit process(PaymentAudit bean) throws Exception {
return bean;
}
}
repo:
package com.spring_batchjob.repository;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import com.spring_batchjob.bean.PaymentAudit;
#Repository
public interface PaymentAuditRepository extends
MongoRepository<PaymentAudit, String> {
// List<PaymentAudit> findByCreateDttmBetween(LocalDateTime createStart,
LocalDateTime createEnd);
List<PaymentAudit> findByRxFNameAndRxLName(String rxFName, String
rxLName);
}
Error after running app:
2018-10-26 13:26:34.256 WARN 16376 --- [ restartedMain]
ConfigServletWebServerApplicationContext : Exception encountered during
context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error
creating bean with name 'paymentPortalJob': Unsatisfied dependency expressed
through field 'jobBuilderFactory'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException: Error
creating bean with name
'org.springframework.batch.core.configuration.annotation.
SimpleBatchConfiguration': Unsatisfied dependency expressed through field
'dataSource'; nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean
with name 'dataSource' defined in class path resource
[org/springframework/boot/autoconfigure/jdbc/
DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method
failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to instantiate
[com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw
exception; nested exception is
org.springframework.boot.autoconfigure.jdbc.
DataSourceProperties$DataSourceBeanCreationException: Failed to determine a
suitable driver class

Cannot resolve reference to bean 'mongoTemplate' while setting bean property 'mongoOperations'

there are few answers to the question already. But none of them works for me.
I can't figure it out for the life of me why the error is coming.
Following are the approaches I tried:
using AbstractMongoConfiguration
Manually registering the mongoTemplate bean with ApplicationContext
Whenever I try to run my test during maven build or while deploying on tomcat error below comes up
Here is the configuration.
package com.fordit.project.config;
#Configuration
#EnableMongoRepositories(basePackages = "com.company.project")
#ComponentScan(basePackages = "com.company.project")
public class ProjectConfiguration {
#Value("${project.db.driver_class}")
private String driverClassname;
#Value("${project.db.connection_string}")
private String connectionString;
#Bean
public DataSource dataSource() throws PropertyVetoException {
Properties mysqlProperties = new Properties();
mysqlProperties.setProperty("characterEncoding", "UTF-8");
mysqlProperties.setProperty("useUnicode", "true");
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setProperties(mysqlProperties);
cpds.setDriverClass(driverClassname);
cpds.setJdbcUrl(connectionString);
cpds.setAcquireIncrement(2);
return cpds;
}
#Bean
public static PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer() throws IOException {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ResourceLoader resourceLoader = new PathMatchingResourcePatternResolver();
ppc.setLocations(
resourceLoader.getResource(System.getProperty("PROJECT_CONFIGURATION_FILE")));
return ppc;
}
#Bean
public static RoleHierarchy roleHierarchy() {
String roleHierarchyStringRepresentation
= Role.ROLE_ADMIN + " > " + Role.ROLE_FIRM + "\n"
+ Role.ROLE_FIRM + " = " + Role.ROLE_LAWYER+ "= "+Role.ROLE_USER;
//logger.info("Registered Role Hierarchy: \n{}", roleHierarchyStringRepresentation);
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy(roleHierarchyStringRepresentation);
return roleHierarchy;
}
}
Mongo Configuration:
#Configuration
#ComponentScan(basePackages = "com.company.project")
#Profile("container")
public class MongoDBConfiguration extends AbstractMongoConfiguration {
#Value("${project.mongodb.hostname}")
private String host;
#Value("${project.mongodb.port}")
private Integer port;
#Value("${project.mongodb.name}")
private String db;
#Value("${project.mongodb.username}")
private String username;
#Value("${project.mongodb.password}")
private String password;
#Value("${project.mongodb.authenticationDB}")
private String authDB;
#Bean
public MongoTemplate mongoTemplate()
throws UnknownHostException, java.net.UnknownHostException {
return new MongoTemplate(
new SimpleMongoDbFactory(
mongoClient(),
getDatabaseName()
)
);
}
#Override
#Bean
public MongoClient mongoClient() {
MongoClient mongoClient = null;
try {
mongoClient = new MongoClient(
new ServerAddress(host, port),
Collections.singletonList(
MongoCredential.createMongoCRCredential(
username,
authDB,
password.toCharArray()
)
)
);
} catch (java.net.UnknownHostException ex) {
Logger.getLogger(MongoDBConfiguration.class.getName()).log(Level.SEVERE, null, ex);
}
return mongoClient;
}
#Override
protected String getDatabaseName() {
return db;
}
}
Error log:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'forumDAL' defined in file [/home/ashay/projects/kuber/target/classes/com/fordit/kuber/forum/ForumDAL.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'forumRepository': Cannot resolve reference to bean 'mongoTemplate' while setting bean property 'mongoOperations'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mongoTemplate' available
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:729)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1270)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:541)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:107)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:243)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
... 26 more
Get rid of the Profile("container") in MongoDBConfiguration.
Explanation: Because the #Profile is there, that means that that class will not be instantiated by Spring unless you are running Spring with that profile. My guess is that you are not setting spring.profiles.active property to "container" when you run your application via Tomcat or during your integration testing.
If you want to leave the #Profile("container") there then just make sure you set the profile to "container". There are multiple ways to do this. One quick easy way is to use Java system properties, e.g. -Dspring.profiles.active=container, when you execute your integration tests or run your application in Tomcat.

BeanNotOfRequiredTypeException when using spring-statemachine and spring cloud slueth

I am currently developing a microservice using spring-boot.I currently have an issue when using spring-state machine and spring-cloud-sleuth artifacts together.
#Validated
#RestController
#SuppressWarnings({"squid:S00112"})
#RequestMapping()
public class StatusController {
#Autowired
private QuoteService quoteService;
#Autowired
private StateMachine<StateMachineDefinition.States, StateMachineDefinition.Events> stateMachine;
#Autowired
private QuoteStateHandler quoteStateHandler;
#Value("${StateMachine.InvalidField.message}")
private String statusInvalidField;
#Value("${StateMachine.QuoteCannotBeNull.message}")
private String quoteStatusNull;
private static final String STATUS = "STATUS";
#InitBinder
public void initBinder(WebDataBinder binder, WebRequest request) {
binder.setAllowedFields("status");
}
/*
Possible state transitions for the specific quote.
*/
#RequestMapping(method = RequestMethod.GET, value = {"/quotes/{quoteId}/transitions", "/{internalClient:(?:ui|s2s)}/{version:^[v]+[0-9]+$}/quotes/{quoteId}/transitions"})
public List<Status> getPossibleTransitions(#PathVariable("quoteId") String id) {
String persistedStatus = quoteService.findOne(id).getStatus();
if (persistedStatus == null) {
persistedStatus = StateMachineDefinition.States.IN_PROCESS.name();
}
Collection<Transition<StateMachineDefinition.States, StateMachineDefinition.Events>> transitions = stateMachine.getTransitions();
String currentState = persistedStatus;
ArrayList<Status> possibleTransistions = new ArrayList<>();
Iterator<Transition<StateMachineDefinition.States, StateMachineDefinition.Events>> iterator = transitions.iterator();
String state;
while (iterator.hasNext()) {
Transition<StateMachineDefinition.States, StateMachineDefinition.Events> transition = iterator.next();
state = transition.getSource().getId().name();
if (state.compareTo(currentState) == 0) {
possibleTransistions.add(new Status(transition.getTrigger().getEvent().toString()));
}
}
return possibleTransistions;
}
#RequestMapping(method = RequestMethod.GET, value = {"/{internalClient:(?:ui)}/{version:^[v]+[0-9]+$}/states"})
public List<String> getStates() {
Collection<State<StateMachineDefinition.States, StateMachineDefinition.Events>> states = stateMachine.getStates();
Iterator<State<StateMachineDefinition.States, StateMachineDefinition.Events>> iterator = states.iterator();
List<String> stateList = new ArrayList<>();
while (iterator.hasNext()) {
State<StateMachineDefinition.States, StateMachineDefinition.Events> state = iterator.next();
stateList.add(state.getId().toString());
}
return stateList;
}
/*
Status is not a state but a transition or event.
*/
#RequestMapping(method = RequestMethod.POST, value = {"{quoteId}/transitions", "/{internalClient:(?:ui|s2s)}/{version:^[v]+[0-9]+$}/quotes/{quoteId}/transitions"})
#ResponseStatus(HttpStatus.NO_CONTENT)
public void postStatus(#RequestBody #Validated(Groups.Api.class) Status status, #PathVariable("quoteId") #Pattern(regexp = Patterns.UUID) String id, BindingResult bindingResult) throws Exception {
if (bindingResult.hasErrors()) {
throw new BadRequestValidationException(STATUS, statusInvalidField);
}
//get quoteid current status
Quote currentQuote = quoteService.findOne(id);
if (currentQuote.getStatus() != null) {
StateMachineDefinition.States currentQuoteState = StateMachineDefinition.States.valueOf(currentQuote.getStatus());
//need to send the event and let the state listener evaluate.
if (status.getStatus() != null) {
quoteStateHandler.handleEvent(
MessageBuilder
.withPayload(StateMachineDefinition.Events.valueOf(status.getStatus()))
.setHeader("quote-id", id)
.build(), currentQuoteState);
}
if (stateMachine.getExtendedState().getVariables().containsKey("ERROR")) {
Exception exception = (Exception) stateMachine.getExtendedState().getVariables().get("ERROR");
stateMachine.getExtendedState().getVariables().clear();
throw exception;
}
if (stateMachine.getState().getId() != currentQuoteState) {
quoteService.updateStatus(id, stateMachine.getState().getId());
}
} else {
//If a quote has null status then it wasnt created properly.
throw new BadRequestValidationException(STATUS, quoteStatusNull);
}
}
}
i didn't had any issues until I added the dependency of spring-cloud sleuth and the error popped up when I started doing the "mvn clean install".
Error stack trace:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stateMachine': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'stateMachineTaskExecutor' is expected to be of type [org.springframework.core.task.TaskExecutor] but was actually of type [org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
... 44 common frames omitted
The error message
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stateMachine': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'stateMachineTaskExecutor' is expected to be of type [org.springframework.core.task.TaskExecutor] but was actually of type [org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor]
Here is the pom.xml file with the two dependencies
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>1.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>LATEST</version>
<dependency>
How should I let the spring application context know which type specifically it has to load?Since both the classes are using the same executor from java util package.
java.util.concurrent.Executor
As presented in the comments it got fixed in the 1.0.12 and 1.1.1 and 1.2.0

Java Spring AOP Logger

I have the follwoing aspect:
#Component
#Aspect
public class LoggingAspect {
Logger logger = Logger.getLogger(LoggingAspect.class);
#AfterReturning(pointcut = "execution(* com.example..*.*(..))", returning = "retVal")
public void logAfterMethod(JoinPoint joinPoint, Object retVal) {
StringBuffer logMessage = new StringBuffer();
logMessage.append(joinPoint.getTarget().getClass().getName());
logMessage.append(".");
logMessage.append(joinPoint.getSignature().getName());
logMessage.append("(");
// append args
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
logMessage.append(args[i]).append(",");
}
if (args.length > 0) {
logMessage.deleteCharAt(logMessage.length() - 1);
}
logMessage.append(")");
if (retVal != null) {
logMessage.append(" with return value " + retVal + " of type "
+ retVal.getClass());
} else {
logMessage.append(" with return value null");
}
logger.info(logMessage);
}
}
and then the following bean:
#Bean
public LoggingAspect logger(){
return new LoggingAspect();
}
but whenever I want to run my application it gives me the errors, I have google it but could not find any related problem to this one, maybe I am missing something ://
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'embeddedServletContainerCustomizerBeanPostProcessor': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': BeanPostProcessor before instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': BeanPostProcessor before instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
Caused by: java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException
The main reason is: nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld.
This means you have to add the aspectjweaver.jar to your classpath.
If you use maven, add the dependency to your pom.xml:
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>

Spring boot not executing schema.sql script

I'm developing a Spring Boot web application and want to create a MySql database if it's not already created. So I've done a dump of my current database in order to have an empty schema of it. Put it in /src/main/resources, so maven brings it to /WEB-INF/classes when building the war file. That's how my application.properties is configured (according to Spring docs, that should create the DB from the script):
# DataSource settings: set here configurations for the database connection
spring.datasource.url = jdbc:mysql://localhost:3306/working_zones
spring.datasource.username = root
spring.datasource.password = password
spring.datasource.driverClassName = com.mysql.jdbc.Driver
# Specify the DBMS
spring.jpa.database = MYSQL
# Hibernate settings are prefixed with spring.jpa.hibernate.*
spring.jpa.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
And that's the error I get when I try to run the application (it complains about a non-existing DB):
2015-01-13 13:30:24.334 [main] ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.UncategorizedScriptException: Failed to execute database script; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'working_zones'
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:301) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1186) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:370) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1095) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:990) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) ~[spring-beans-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:975) ~[spring-context-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:752) ~[spring-context-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) ~[spring-context-4.0.8.RELEASE.jar:4.0.8.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109) ~[spring-boot-1.1.9.RELEASE.jar:1.1.9.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691) [spring-boot-1.1.9.RELEASE.jar:1.1.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) [spring-boot-1.1.9.RELEASE.jar:1.1.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952) [spring-boot-1.1.9.RELEASE.jar:1.1.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941) [spring-boot-1.1.9.RELEASE.jar:1.1.9.RELEASE]
So it seems that Spring tries to connect to the database even schema.sql, which contains the script to create the DB, not executed. There are some related questions in Stack Overflow about that, but still can't get it working, even if I try with spring.datasource.initialize=true...
Well, looks like you can't do that from the common JDBC connect: creating a database in mysql from java
Hence Spring Boot can't do that for you automatically.
Please, don't mix the DB creating with its creation for its content: tables, procedures, triggers etc.
UPDATE
Yes, you can do that on the application startup. You just a separate initializer, which has an order before dataSourceInitializer.
A listerner on the application startup can resolve it. Following is the code.
public class DatabaseCreationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
private AtomicBoolean received = new AtomicBoolean(false);
private ConfigurableEnvironment environment;
private Pattern JDBC_URL_PATTERN = Pattern.compile("jdbc:([a-zA-Z0-9_]+)://[0-9.:]+(?:/([a-zA-Z0-9_]+))?(\\?.*)?");
#Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
// Think about twice invoking this listener
if (!received.compareAndSet(false, true)) {
return;
}
environment = event.getEnvironment();
// ConditionalOnClass
ClassLoader classLoader = event.getSpringApplication().getClassLoader();
if (!isPresent("org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType", classLoader)) {
return;
}
// DatabaseProperties
val databaseProperties = bind(DatabaseProperties.PREFIX, new DatabaseProperties());
if (!databaseProperties.shouldCreate()) {
return;
}
// DataSourceProperties
val dataSourceProperties = bind(databaseProperties.getDatasourceConfigPrefix(), new DataSourceProperties());
// Check for connection url
String url = dataSourceProperties.getUrl();
if (url == null) return;
Matcher matcher = JDBC_URL_PATTERN.matcher(url);
if (!matcher.matches()) return;
// Extract database provider and schema name from connection url
String databaseProvider = matcher.group(1);
String schemaName = matcher.group(2);
if (isBlank(schemaName)) return;
// Reset connection url
dataSourceProperties.setUrl(url.replace("/" + schemaName, ""));
// Build a new datasource and do create schema
DataSource dataSource = buildDataSource(dataSourceProperties);
try (Connection connection = DataSourceUtils.getConnection(dataSource)) {
connection.createStatement().execute(createSchemaIfAbsent(databaseProvider, schemaName));
} catch (SQLException ignored) {
}
}
private <T> T bind(String prefix, T t) {
RelaxedDataBinder binder = new RelaxedDataBinder(t, prefix);
binder.bind(new PropertySourcesPropertyValues(environment.getPropertySources()));
return t;
}
private static DataSource buildDataSource(DataSourceProperties dataSourceProperties) {
String url = dataSourceProperties.getUrl();
String username = dataSourceProperties.getUsername();
String password = dataSourceProperties.getPassword();
return new SingleConnectionDataSource(url, username, password, false);
}
private static String createSchemaIfAbsent(String databaseProvider, String schemaName) {
DatabaseDialects dialects = DatabaseDialects.getDatabaseDialect(databaseProvider);
if (dialects == null) {
throw new IllegalArgumentException("Unknown schema:" + schemaName);
}
switch (dialects) {
case MYSQL:
return "CREATE DATABASE IF NOT EXISTS " + schemaName;
default:
throw new UnsupportedOperationException("Unsupported schema:" + dialects);
}
}
}
And Following is the DatabaseProperties.
#Data
#ConfigurationProperties(prefix = DatabaseProperties.PREFIX)
public class DatabaseProperties {
public final static String PREFIX = "spring.database";
private boolean autoCreate;
private String datasourceConfigPrefix = "spring.datasource";
public boolean shouldCreate() {
return isAutoCreate() && isNotBlank(getDatasourceConfigPrefix());
}
}
The listener should be actived by config in META-INF/spring.factories.
org.springframework.context.ApplicationListener=\
yourpackage.DatabaseCreationListener
If you want config syntax hint in an underlying IDE, add the optional depenedncy spring-boot-configuration-processor and file META-INF/additional-spring-configuration-metadata.json.
{
"groups": [
{
"sourceType": "yourpackage.DatabaseProperties",
"name": "spring.database",
"type": "yourpackage.DatabaseProperties"
}
],
"properties": [
{
"sourceType": "yourpackage.DatabaseProperties",
"defaultValue": false,
"name": "auto-create",
"type": "java.lang.Boolean"
},
{
"sourceType": "youpackage.DatabaseProperties",
"defaultValue": "spring.datasource",
"name": "datasource-config-prefix",
"type": "java.lang.String"
}
]
}
As mentioned in this github post, you can add:
spring.datasource.url=jdbc:mysql://localhost:3309/course_api_db?createDatabaseIfNotExist=true
To execute the schema.sql

Categories