Spring JDBC : unable to get dataSource - java

I have a spring XML config file called appConfig.xml which contains a datasource bean and another JDBCtemplate to which datasource is passed as an argument:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
</bean>
<bean id="JDBCTemplate" class="com.myprojects.JDBCTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
I get an error :
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'JDBCTemplate' defined in file [appConfig.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'dataSource' threw exception; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required
From what I see from this error, it is not able to pass dataSource to JDBCTemplate. The logs also says:
Loaded JDBC driver: com.mysql.jdbc.Driver
I have all dependencies mentioned in pom.xml and I verified that necessary jars for spring are loaded and mysql jdbc connector is also loaded. Any clues on what the issue may be?
I tried a different project where I manually added all spring dependencies and mysql jdbc connector as part of library. It worked fine there. But while trying to include dependencies via pom.xml, I'm facing this issue. So I'm assuming this is to do with some dependency not being pulled in or something. But unable to figure out which one from the error.

It thinks your class JDBCTemplate does not have a property named dataSource
Perhaps you don't have a public method setDataSource() that has a single argument of the right type.
Perhaps it is private.
Perhaps it is spelled wrong.

Related

How do include a property at runtime in a spring context?

How do I add properties at runtime and use them to populate placeholders in my context files?
First, a little background: I have a batch data loader which loads a database. I have a requirement that the database password is not stored on disk for this program, so I allow the user to enter it interactively.
I am using hibernate, and my datasource is configured in a context file, with the actual parameters in another properties file.
Some attributes of what I'm looking for
The property is available only at runtime (user entered password)
It can be provided before the context loads
It doesn't need to dynamically change
Other related properties are still loaded via a normal properties file
db.xml:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
and so on...
</bean>
database.properties:
hibernate.connection.username=Username
### hibernate.connection.password= #don't want the password stored
hibernate.connection.url=<the url>
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
And my main context.xml:
<import resource="classpath:db.xml" />
<context:property-placeholder location="classpath:database.properties" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:database.properties" />
</bean>
plus more...
What I want to do is add a new property (hibernate.connection.password) to the context before refreshing it at runtime so that the corresponding value is replaced in db.xml.
My current attempt looks like this
Properties prop = new Properties();
prop.setProperty("hibernate.connection.password", thePassword);
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setProperties(prop);
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"my-context.xml"}, false); // Don't refresh after loading
ctx.addBeanFactoryPostProcessor(ppc);
ctx.refresh();
I must be doing something wrong, however, since I get an exception that tells me the properties from my database.properties file are not being used.
2016-03-14 14:58:41 WARN ClassPathXmlApplicationContext:546 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [db.xml]: Could not resolve placeholder 'hibernate.connection.driver_class' in string value "${hibernate.connection.driver_class}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'hibernate.connection.driver_class' in string value "${hibernate.connection.driver_class}"
To be sure my setup for the database.properties file is correct, if I remove the call to ctx.addBeanFactoryPostProcessor(ppc), I instead get an exception complaining about the missing password
2016-03-14 16:52:10 WARN ClassPathXmlApplicationContext:546 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [db.xml]: Could not resolve placeholder 'hibernate.connection.password' in string value "${hibernate.connection.password}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'hibernate.connection.password' in string value "${hibernate.connection.password}"
Error: Invalid bean definition with name 'dataSource' defined in class path resource [db.xml]: Could not resolve placeholder 'hibernate.connection.password' in string value "${hibernate.connection.password}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'hibernate.connection.password' in string value "${hibernate.connection.password}"
And if the password is present in the properties file, everything works fine.
My question then is how do I cause both the database.properties and the runtime-defined property to post-process my context files?
Edit
One solution I have found is to manually load the properties file into the PropertyPlaceholderConfigurer.
ppc.setLocation(new ClassPathResource("database.properties"));
This works, however the property set programmatically will be overridden by any matching property in the properties file, which makes it feel like a workaround. Also, I still don't understand why both PropertyPlaceholderConfigurers don't get used (the one defined in the context file and the one defined in java)
In order for Spring to read the properties from database.properties you'll have to define a bean of Properties Placeholder like below:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database.properties</value>
</property>
</bean>
Then you can use it in your dataSource bean as follows:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
and so on...
</bean>
If you want to pass the password at run-time then you can pass it as an argument as follows:
-Dhibernate.connection.password=<password>

neo4j allow_store_upgrade causing application not to start

I am trying to setup a spring project with neo4j. However, when I run the application it does not start up and give the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'videoRepository': Cannot resolve reference to bean 'neo4jTemplate' while setting bean property 'neo4jTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.data.neo4j.config.Neo4jConfiguration#0': Cannot resolve reference to bean 'graphDatabaseService' while setting bean property 'graphDatabaseService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphDatabaseService' defined in class path resource [spring/neo4j.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.neo4j.kernel.EmbeddedGraphDatabase]: Constructor threw exception; nested exception is java.lang.RuntimeException: org.neo4j.kernel.lifecycle.LifecycleException: Component 'org.neo4j.kernel.impl.transaction.XaDataSourceManager#147e32a' was successfully initialized, but failed to start. Please see attached cause exception.
org.neo4j.kernel.impl.storemigration.StoreUpgrader$UnableToUpgradeException: Not all store files match the version required for successful upgrade
Here is my neo4j.xml
<neo4j:repositories base-package="neo4j.repository"/>
<neo4j:config graphDatabaseService="graphDatabaseService"/>
<bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase" destroy-method="shutdown">
<constructor-arg value="C:/Users/mario/Documents/Neo4j/default.graphdb"/>
<constructor-arg>
<map>
<entry key="allow_store_upgrade" value="true"/>
</map>
</constructor-arg>
</bean>
I am assuming that this problem is caused by allow_store_upgrade. If I remove or set this property to false a exception is thrown suggesting to me to set it to true. What is really causing this problem and how can I fix it?

Issue with Spring-DM OSGI Service and #Autowired

I am facing an issue with Spring-DM and #Autowired with Osgi Services.
I have defined a Spring bean + OSGI Service as following:
<bean id="my.sessionFactoryBean"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref local="my.dataSource" />
</property>
...
</bean>
<osgi:service ref="my.sessionFactoryBean"
id="my.sessionFactory" interface="org.hibernate.SessionFactory" />
I can reference, from another bundle, this service without any problem in an xml bean definiton like following:
<beans>
...
<osgi:reference id="my.sessionFactory"
interface="org.hibernate.SessionFactory" />
..
<bean id="my.databaseItemReader"
class="my.MyReader">
<property name="sessionFactory" ref="my.sessionFactory" />
...
</beans>
My problem relies on using the #Autowired anotation like following:
public abstract class AbstractHibernateDao {
#Autowired
#Qualifier(value="my.sessionFactory")
private SessionFactory sessionFactory;
...
I am getting the classic error:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.Sess
ionFactory my.AbstractHibernateDao.sessionFactory; nested exception is org.springfr
amework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.hibernate.SessionFactory] found for d
ependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {
#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qu
alifier(value=my.sessionFactory)}
If I remove the #Qualifier, I get this error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [my.sessionFactoryBean, my.sessionFactory]
Which makes me think that I do have my OSGI-Service in the Spring bean registry ...
Any ideas what I am doing wrong?
FYI, I have also tried to inject OSGI-services with #ServiceReference on the setter, but Spring-DM never injects it (have some nullpointerexception)
Just a guess but when you use #Autowire, you must be doing "context:component-scan" and this in turn might be finding the additional bean that is showing up (my.sessionFactoryBean). When injected using XML, perhaps the component scan is not enabled and hence the OSGi service is properly getting resolved.

Error creating bean ... could not load JDBC driver class [oracle.jdbc.driver.OracleDriver]

I have written code to run a query using JDBC on Spring but I get an exception (see below)
Here's my context.xml
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#Mohsen-PC:1521:mydb"/>
<property name="username" value="system"/>
<property name="password" value="123"/>
</bean>
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler">
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/>
</bean>
<bean id="nativeJdbcExtractor"
class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
main.java
import javax.sql.DataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
class Main {
public static void main(String args[]) throws Exception {
ApplicationContext ac = new ClassPathXmlApplicationContext("context.xml");
DataSource dataSource = (DataSource) ac.getBean("dataSource");
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
System.out.println(jdbcTemplate.queryForList("select EMPLOYEE_ID from EMPLOYEE",
Long.class));
}
}
The exception I see is:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataSource' defined in class path resource [context.xml]:
Error setting property values; nested exception is
org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException:
Property 'driverClassName' threw exception; nested exception is
java.lang.IllegalStateException: Could not load JDBC driver class
[oracle.jdbc.driver.OracleDriver] at
org.springframework.beans.factory.support.
AbstractAutowireCapableBeanFactory.applyPropertyValues(
AbstractAutowireCapableBeanFactory.java:1396)
EDIT: cut remainder of stack trace as the above exception is sufficient to illuminate the problem.
What is going wrong here?
Looks like you are missing the oracle jdbc driver in your classpath. Please download the jar file from this path and add this to your classpath.
EDITED
Spring jdbc is a template layer which works on top of the raw jdbc layer. It just provides us some utility methods to make the database access easier. This layer internally needs the jdbc layer to work so which every database you want to connect to that database's driver also has to be included, in your case you need to include Oracle driver.
It looks like the (Oracle-supplied) jar file with the JDBC driver is not in your classpath.
Note the part of the stack trace that says: "IllegalStateException: Could not load JDBC driver class [oracle.jdbc.driver.OracleDriver"
In my case the problem was fixed setting the scope to runtime:
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.0.0.jre8</version>
<scope>runtime</scope>
</dependency>
Reference: When would I need maven dependency with runtime scope

java.lang.NoClassDefFoundError for my DAO

i am using spring.xml for my controller and dao configuration. my spring-config.xml is as below:
<bean id="courseDao" class="com.platysgroup.lmex.adapter.moodle.dao.CourseDao"
init-method="setMoodleDataSource" depends-on="moodleAuthenticationDetails">
<property name="adapterDataSource" ref="adapterDataSource"></property>
<property name="userDao" ref="userDao"></property>
<property name="announcementDao" ref="announcementDao"></property>
<property name="roleDao" ref="roleDao"></property>
<property name="logDao" ref="logDao"></property>
</bean>
i have a coursedao class in my project in the package com.platysgroup.lmex.adapter.moodle.dao in the project name lmex-impl. but my spring config is not getting the class from a lmex-impl.jar. the spring-config.xml is on lmex-web project. and other thing is that he is showing me a wrong path in exception. the wrong name is Lcom/platysgroup/lmex/adapter/moodle/dao/CourseDao; instead of com/platysgroup/lmex/adapter/moodle/dao/CourseDao; the exception full stacktrace is as below:
javax.servlet.ServletException: Servlet.init() for servlet Spring MVC Dispatcher Servlet threw exception
org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:195)
org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:159)
org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:141)
org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:90)
org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:417)
root cause
java.lang.NoClassDefFoundError: Lcom/platysgroup/lmex/adapter/moodle/dao/CourseDao;
java.lang.Class.getDeclaredFields0(Native Method)
java.lang.Class.privateGetDeclaredFields(Class.java:2291)
java.lang.Class.getDeclaredFields(Class.java:1743)
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:315)
org.springframework.context.annotation.CommonAnnotation.........
java.lang.ClassNotFoundException: com.platysgroup.lmex.adapter.moodle.dao.CourseDao
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387)
please help me to resolve this.
Thank you
A NoClassDefFoundError is thrown when the JRE can't find a class. In your case, it can't find the class Lcom/platysgroup/lmex/adapter/moodle/dao/CourseDao, which you most probably did not add to your classpath.
The prefix 'L' indicates the instance of class. Please see Field Descriptors. You should focus on finding issue with configuration of bean courseDao and check that its all dependencies are there in same application context.

Categories

Resources