Spring Boot: Unable to look up data source - spring-boot

I'm running an application framework (jbpm) on Spring Boot which requires looking up a Datasource.
I'm facing the following error:
java.lang.RuntimeException: Unable to look up data source: java:jboss/datasources/ExampleDS - Need to specify class name in environment or system property, or in an application resource file: java.naming.factory.initial
at org.jbpm.process.workitem.executesql.ExecuteSqlWorkItemHandler.<init>(ExecuteSqlWorkItemHandler.java:83) ~[execute-sql-workitem-7.52.0.Final.jar:7.52.0.Final]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
I have got the following properties in application.properties:
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
#hibernate configuration
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
I have also added in my configuration class the following:
#Bean
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:jboss/datasources/ExampleDS");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource) bean.getObject();
}
I have checked the code of the jbpm handler:
https://github.com/kiegroup/jbpm-work-items/blob/main/execute-sql-workitem/src/main/java/org/jbpm/process/workitem/executesql/ExecuteSqlWorkItemHandler.java#L79
I see this is the code which does the lookup:
this.ds = InitialContext.doLookup(dataSourceName);
What am I missing in my code/configuration?
Thanks
Edit: here's the core section of pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.10.RELEASE</version>
</parent>
<properties>
<version.org.kie>7.52.0.Final</version.org.kie>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<narayana.version>5.9.0.Final</narayana.version>
<fabric8.version>3.5.40</fabric8.version>
</properties>
<dependencies>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-server-spring-boot-starter</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.jbpm.contrib</groupId>
<artifactId>execute-sql-workitem</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

Related

SpringTemplateEngine setRenderHiddenMarkersBeforeCheckboxes method did not exist

I am creating a web application with SpringBoot and Thymeleaf layouts. Once I start the application, I get the following error while using Thymeleaf.
The following method did not exist:
org.thymeleaf.spring5.SpringTemplateEngine.setRenderHiddenMarkersBeforeCheckboxes(Z)V
My POM :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.4.1</thymeleaf-layout-dialect.version>
</properties>
...
<dependency>
...
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
Java Config :
#Bean
public LayoutDialect layoutDialect() {
return new LayoutDialect();
}
Any idea?
Turned out to be a version issue. Solved it by changing the thymeleaf.version to thymeleaf-spring5.version in properties
<properties>
<java.version>1.8</java.version>
<!--<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>-->
<thymeleaf-spring5.version>3.0.9.RELEASE</thymeleaf-spring5.version>
<thymeleaf-layout-dialect.version>2.4.1</thymeleaf-layout-dialect.version>
</properties>

c3p0 hsqldb driver class not found

I am trying to create a simple web service with spring hibernate and maven. when I try to execute the project c3p0 cannot find the driver class. I am trying to connect to HSQLDB as standalone NOT embedded mode.
the error that I get is:
May 02, 2019 12:17:08 PM com.mchange.v2.c3p0.DriverManagerDataSource
WARNING: Could not load driverClass org.hsqldb.jdbc.JDBCDriver
java.lang.ClassNotFoundException: org.hsqldb.jdbc.JDBCDriver
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1291)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.mchange.v2.c3p0.DriverManagerDataSource.ensureDriverLoaded(DriverManagerDataSource.java:143)
at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:173)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:220)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:206)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:203)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1138)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1125)
at com.mchange.v2.resourcepool.BasicResourcePool.access$700(BasicResourcePool.java:44)
at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1870)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)
I validated that the JAR file is there and I created another project with just hibernate and c3p0 and everything is working fine. the problem arises when I include spring.
here is my POM file
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.luv2code.springdemo</groupId>
<artifactId>spring-crm-rest</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<springframework.version>5.0.6.RELEASE</springframework.version>
<hibernate.version>5.4.1.Final</hibernate.version>
<mysql.connector.version>5.1.45</mysql.connector.version>
<c3po.version>0.9.5.2</c3po.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Add Jackson for JSON converters -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- MySQL -->
<!-- <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version> </dependency> -->
<!-- https://mvnrepository.com/artifact/org.hsqldb/hsqldb -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.4.1</version>
<scope>test</scope>
</dependency>
<!-- C3PO -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3po.version}</version>
</dependency>
<!-- Servlet+JSP+JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- to compensate for java 9 not including jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<finalName>spring-crm-rest</finalName>
<plugins>
<!-- Builds a Web Application Archive (WAR) file from the project output
and its dependencies. -->
<plugin>
<!-- Add Maven coordinates (GAV) for: maven-war-plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</build>
</project>
here is my config class
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#ComponentScan("com.luv2code.springdemo")
#PropertySource({ "classpath:persistence-mysql.properties" })
public class DemoAppConfig implements WebMvcConfigurer {
#Autowired
private Environment env;
private Logger logger = Logger.getLogger(getClass().getName());
// define a bean for ViewResolver
#Bean
public DataSource myDataSource() {
// create connection pool
ComboPooledDataSource myDataSource = new ComboPooledDataSource();
// set the jdbc driver
try {
myDataSource.setDriverClass(env.getProperty("jdbc.driver"));
}
catch (PropertyVetoException exc) {
throw new RuntimeException(exc);
}
// for sanity's sake, let's log url and user ... just to make sure we are reading the data
logger.info("jdbc.url=" + env.getProperty("jdbc.url"));
logger.info("jdbc.user=" + env.getProperty("jdbc.user"));
// set database connection props
myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
myDataSource.setUser(env.getProperty("jdbc.user"));
myDataSource.setPassword(env.getProperty("jdbc.password"));
// set connection pool props
myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));
myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));
return myDataSource;
}
private Properties getHibernateProperties() {
// set hibernate properties
Properties props = new Properties();
props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
return props;
}
// need a helper method
// read environment property and convert to int
private int getIntProperty(String propName) {
String propVal = env.getProperty(propName);
// now convert to int
int intPropVal = Integer.parseInt(propVal);
return intPropVal;
}
#Bean
public LocalSessionFactoryBean sessionFactory(){
// create session factorys
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
// set the properties
sessionFactory.setDataSource(myDataSource());
sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
sessionFactory.setHibernateProperties(getHibernateProperties());
return sessionFactory;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
// setup transaction manager based on session factory
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
}
and here is my propertis file.
#
# JDBC connection properties
#
jdbc.driver=org.hsqldb.jdbc.JDBCDriver
jdbc.url=jdbc:hsqldb:hsql://localhost/testdb
jdbc.user=SA
jdbc.password=
#
# Connection pool properties
#
connection.pool.initialPoolSize=5
connection.pool.minPoolSize=5
connection.pool.maxPoolSize=20
connection.pool.maxIdleTime=3000
#
# Hibernate properties
#
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true
hibernate.packagesToScan=com.luv2code.springdemo.entity
Remove <scope>test</scope> from your HSQLDB dependency. With scope test, you can only use it in tests, not in normal code. See also What is <scope> under <dependency> in pom.xml for?
Your HSQLDB Dependency in "test" scope, so it will not be carried away when application running. Change test become compile

"resources" folder not being created in WEB-INF directory in Spring Boot app

I have a Spring Boot application in development that I recently upgraded from Spring 3 to Spring 4 (spring-boot-starter-parent 1.3.5.RELEASE to 1.4.6.RELEASE).
I have, within my src/main/resources/templates directory, an html template (called 'test-template.html') which I have been using to create HTML email content, using Thymeleaf's TemplateEngine. (This was working fine prior to upgrading to version 4.)
The problem I have at present is that no "templates" directory is being created within WEB-INF on the server (or within the relevant directory within "target", upon building with Maven). As a result, I'm getting the following:
java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/templates/test-template.html]
The following is my configuration class for Thymeleaf. (I am using manual configuration since I'm using Thymeleaf only for email template processing, and thus don't want Spring Boot to configure a Thymeleaf view resolver. I get the same error with auto-configuration, however.)
#Configuration
public class ThymeleafConfig implements ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(ThymeleafConfig.class);
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
return engine;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
}
Here's the pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>1.0.10-SNAPSHOT</version>
<packaging>war</packaging>
<name>myapp</name>
<description>blah blah</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<start-class>com.matchingchina.AcumenApplication</start-class>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.sendgrid</groupId>
<artifactId>sendgrid-java</artifactId>
<version>3.2.1</version>
</dependency>
<!-- WEBJARS -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.6</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>font-awesome</artifactId>
<version>4.6.1</version>
</dependency>
</dependencies>
</project>
Change /WEB-INF/templates/ to classpath:/template/. On the classpath doesn't necessary mean on the web context path.

Could not autowire. There is more than one bean of 'DataSource' type

I'm trying to Autowire a database by
#Autowired
private DataSource dataSource;
I have one datasource in my application.yml
spring:
profiles:
active: dev
---
spring:
profiles: dev
datasource:
driverClassName: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306/dbname
username: user
password: password
name: dev
logging:
level:
org.springframework: INFO
---
spring:
profiles: prod
name: prod
logging:
level:
org.springframework: INFO
But I get an error message saying.
Could not autowire. There is more than one bean of 'DataSource' type.
Beans:dataSource (DataSourceConfiguration.class)
dataSource (DataSourceConfiguration.class)
Which I find strange since I only have one datasource defined in my application.yml and to my knowledge I don't have any other datasource defined.
I gave a try with a config but I still get the same issue.
#Configuration
#EnableConfigurationProperties
public class AppConfig {
#Bean
#ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
}
This is my 'pom' file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>id.group</groupId>
<artifactId>ProjectName</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<!--Spring Boot dependencies-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!--Spring Boot dependencies-->
<!--Spring Security dependencies-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--Spring Security dependencies-->
<!--JWT dependencies-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<!--JWT dependencies-->
<!--Actuator and HAL browser dependencies-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
<!--Actuator and HAL browser dependencies-->
<!--Database dependencies-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>1.5.7</version>
</dependency>
<!--Database dependencies-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I'm using Spring Boot 1.5.2 and IntelliJ 2017.1
Try this it worked for me, use #Primary like this
#Primary
#Bean(name ="prodDataSource")
#ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "prodJdbc")
public JdbcTemplate prodJdbcTemplate(#Qualifier("prodDataSource") DataSource prodDataSource){
return new JdbcTemplate(prodJdbcTemplate);
}
#Bean(name = "devDataSource")
#ConfigurationProperties(prefix = "spring.datasource.dev")
public DataSource devDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "devJdbc")
public JdbcTemplate devJdbcTemplate(#Qualifier("devDataSource") DataSource devDataSource) {
return new JdbcTemplate(devDataSource);
}
And then use #autowire like this
#Autowired
#Qualifier("prodJdbc")
private JdbcTemplate prodJdbcTemplate;
I hope this can help you or someone else :)
Please note that Spring Boot autoconfigured beans are not supported 100% yet, see https://youtrack.jetbrains.com/issue/IDEA-139669 for progress and possible workaorunds.
I solved by adding qualifier above the property:
#Autowired
#Qualifier("dataSource")
private DataSource dataSource;

Spring Boot on Embedded Tomcat with JSTL still throws java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config

I have an application which leverages PrimeFaces, elastic search,Spring boot.
Following is it's pom.xml,
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acn.hps.aops.demo</groupId>
<artifactId>PSCommandCenter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>CommandCentre</name>
<description>Command Center Application</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.geocoder-java</groupId>
<artifactId>geocoder-java</artifactId>
<version>0.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<!-- Primefaces -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>5.2</version>
</dependency>
<dependency>
<groupId>org.primefaces.themes</groupId>
<artifactId>all-themes</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
<version>2.3.4</version>
</dependency>
<!-- JSF dependencies -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.8</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Elastic Search dependencies -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>3.7</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>primefaces</id>
<url>http://repository.primefaces.org</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>
Following is its spring configuration,
#SpringBootApplication
public class CommandCentreApplication extends WebMvcConfigurerAdapter{
public static void main(String[] args) {
SpringApplication.run(CommandCentreApplication.class, args);
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/home.jsf");
}
#Bean
ServletRegistrationBean facesServletRegistration() {
return new ServletRegistrationBean() {
#Override
public void onStartup(ServletContext servletContext)
throws ServletException {
FacesInitializer facesInitializer = new FacesInitializer();
facesInitializer.onStartup(Collections.singleton(CommandCentreApplication.class),
servletContext);
servletContext.setInitParameter("primefaces.THEME", "redmond");
servletContext.setInitParameter("javax.faces.FACELETS_REFRESH_PERIOD", "0");
servletContext.setInitParameter("facelets.SKIP_COMMENTS", "true");
}
};
}
#Bean
ServletRegistrationBean pushServletRegistration(){
ServletRegistrationBean pushServlet = new ServletRegistrationBean(new PushServlet(), "/primepush/*");
pushServlet.addInitParameter("org.atmosphere.annotation.packages", "org.primefaces.push");
pushServlet.addInitParameter("org.atmosphere.cpr.packages", "com.acn.hps.aops.demo.map.service.channel");
pushServlet.setAsyncSupported(true);
pushServlet.setLoadOnStartup(0);
pushServlet.setOrder(Ordered.HIGHEST_PRECEDENCE);
return pushServlet;
}
}
and my elastic search's configuration,
#Bean
public Client client(){
TransportClient client= new TransportClient();
TransportAddress address = new InetSocketTransportAddress(PropertiesLoader.esIP, PropertiesLoader.esPort);
client.addTransportAddress(address);
return client;
}
This same application runs as expected when I execute it from my IDE (Eclipse) but when I execute the application from its jar then I am getting the following exception ,
java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config
at java.net.URLClassLoader.findClass(Unknown Source) ~[na:1.8.0_45].
I searched for this exception and I found that jstl's jar is added to avoid this error. But I already have jstl's jar in tomcat's jar. And also if this is the problem then I should be getting the same exception while executing from my IDE.
You can refer this github code which i used as outline for my application. I am facing the same issue in this also.
When using spring-boot-starter as a parent, running
mvn clean install
should produce a fat jar (that means all dependencies are copied into that jar).
More informations can be found here:
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-build.html
Maybe this part in the spring-boot-starter plugin within the pom.xml
<configuration>
<executable>true</executable>
</configuration>
is messing with this. Try to remove that part and build the jar again.

Resources