I already have an existing application with hibernate and embedded derby working.
My hibernate.cfg.xml has the following settings
<property name="connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property>
<property name="connection.url">jdbc:derby:data;create=true</property>
<property name="connection.username">application</property>
<property name="connection.password">password</property>
<property name="hibernate.default_schema">my_application</property>
everything has been working fine but I wish to add spring boot to that project and I am getting
Failed to create sessionFactory
object.org.hibernate.service.spi.ServiceException: Unable to create
requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
when I am loading the sessionFactory from hibernate. Why can I not do that? Is loading embedded Derby from spring boot the only way? I don't want spring boot to have any relation to the database.
Also, after adding spring boot my log4j.properties file is not read anymore even if I do not run spring boot at all.
Found it. needed to set application.properties like this
spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.DerbyDialect
spring.datasource.url=jdbc:derby:data;create=true
spring.datasource.username=application
spring.datasource.password=password
spring.datasource.driver-class-name=org.apache.derby.jdbc.EmbeddedDriver
spring.datasource.initialize=true
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
my boot app needs a hibernate bean like this
#SpringBootApplication
#EntityScan("core.peristence.dtos")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
#Bean
public HibernateJpaSessionFactoryBean sessionFactory() {
return new HibernateJpaSessionFactoryBean();
}
}
and my service can autowire the sessionFactory now like this:
#Service
public class MyService {
#Autowired
private SessionFactory sessionFactory;
...
}
Related
For my spring boot application I use annotation based configuration and a WebApplicationInitalizer.
One of my dependencies provides a spring configuration in an xml, included in the jar. I use #ImportResource to load the context xml. This seems to work, except for the fact that inside this xml, there are property placeholders, for example ${poolsize:10}
Apparently, spring does not automatically replace these placeholders (I get a NumberFormatException). Is there some extra configuration I need to add?
Our startup class:
public class Application implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
// config
rootContext.register(JmsConfiguration.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
}
}
And the configuration class (we use spring-jms):
#Configuration
#EnableJms
#ComponentScan(basePackages = { "..." })
public class JmsConfiguration implements JmsListenerConfigurer {
// config for jms listener and jaxb, nothing to do with property handling
}
Perhaps I'm mistaken in thinking that using a WebapplicationInitializer is how to use spring boot. Perhaps we don't even need spring boot? The only spring boot related dependency we use is:
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Spring dependencies we use:
org.springframework:spring-context:jar:4.3.8.RELEASE:compile
org.springframework:spring-jms:jar:4.3.8.RELEASE:compile
org.springframework:spring-oxm:jar:4.3.8.RELEASE:compile
org.springframework:spring-context:jar:4.3.8.RELEASE:compile
org.springframework:spring-beans:jar:4.3.8.RELEASE:compile
I figured it out thanks #M. Deinum
We don't need spring boot to use the WebApplicationInitializer, but (at least without spring boot) we have to declare our own PropertySourcesPlaceholderConfigurer:
#Configuration
#ImportResource(locations = {"classpath*:/library-context.xml"})
public class MyConfiguration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
NB. This works out of the box in spring boot thanks to #EnableAutoConfiguration and #PropertyPlaceholderAutoConfiguration which contains the exact same PropertySourcesPlaceholderConfigurer bean
I been searching again for this issue where I cannot locate the jndi database by using java config. Before this I use xml and its work perfectly but in java config it cause an issue;
Xml code:
<!-- Jndi database connection -->
<jee:jndi-lookup id="dbDataSource" jndi-name="${db.jndi}"
resource-ref="true" />
<beans:bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate" >
<beans:property name="dataSource" ref="dbDataSource"></beans:property>
</beans:bean>
Java config now:
#Bean(name = "dbDataSource")
public DataSource dataSource(#Value("${db.jndi}") String jndiName)
{
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiName);
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource ds) {
return new JdbcTemplate(ds);
}
Properties file:
db.jndi=jndi/myData
JNDI name in weblogic:
jndi/myData
After change to java config, sometimes the system can read the database but rarely occur, until I clean and restart my computer then it can find the database, but usually its always trigger:
javax.naming.NameNotFoundException: Unable to resolve 'jndi.myData'. Resolved 'jndi'; remaining name 'myData'
Why the application cannot find the database correctly?
Thanks!!!
I've had the same issue. If you're using 4.x version of spring that's probably the cause.
You should also check Weblogic's JNDI Tree. If your data source disapears from the tree after rebuilding the project, that's another symptom
If that's the case, what's happening is:
Your Datasource implements Closeable (and therefore AutoCloseable) and the context will always invoke the shutdown method regardless of your Bean definition
as seen here : SPR-12551: Document how to prevent a JNDI DataSource retrieved using JavaConfig to be removed on shutdown of the context
It's been marked as a documentation issue as this is the "expected" behaviour:
This issue was solely about documentation since we decided not to implement anything at the framework level
the solution, is to define the destroy method of the bean as empty, such as:
#Bean(name = "dbDataSource", destroyMethod="")
public DataSource dataSource(#Value("${db.jndi}") String jndiName)
{
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiName);
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource ds) {
return new JdbcTemplate(ds);
}
This is described in this issue (SPR-13022:Destroy callback cannot be disabled for AutoCloseable beans) .
PS: By the way, it seems like on early 4.x version of spring you couldn't override this behaviour by assingning destroyMethod. It apears that this bug was fixed on version 4.2 RC1.
I've had the same issue and I solved problem. I used to jndi datasource on weblogic. After I restart application, I notice my jndi datasource remove from Weblogic's JNDI Tree. Xml configuration works successfuly but java configuration don't work.
My old spring version: 4.1.6.RELEASE Upgrade to 4.3.9.RELEASE
Xml configuration like this;
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>${db-jndi.name}</value>
</property>
</bean>
Java configuration like this;
#Bean(name = "dataSource")
public DataSource dataSource() throws IllegalArgumentException, NamingException
{
JndiTemplate jndiTemplate = new JndiTemplate();
DataSource dataSource = (DataSource) jndiTemplate.lookup(env.getProperty("db-jndi.name"));
logger.info("DataSource initialized in jndi ");
return dataSource;
}
Then i changed
#Bean(name = "dataSource")
to
#Bean(name = "dataSource", destroyMethod = "")
And it's works successfuly.
It looks like your datasource hasn't been deployed. You should look for JNDI tree for the server you tried to deploy datasource. (https://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/taskhelp/jndi/ViewObjectsInTheJNDITree.html) If you don't see "jndi.myData" on JNDI tree, you can assume that your datasource haven't been deployed. So you can go to your datasource monitoring tab and test the datasource. (https://docs.oracle.com/cd/E17904_01/apirefs.1111/e13952/taskhelp/jdbc/jdbc_datasources/TestDataSources.html)
In my application,we bind the datasource through the JNDIlook up using below code:
<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/jboss/datasources/efmDS</value>
</property>
</bean>
Dao has code like below:
#Autowired
#Qualifier("jndiDataSource")
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
Now I am having problem while running Junit test case.
I am testing a service method which is annotated with #Transactional.
This service method internally calls some dao method which I have already mocked using mockito but I am facing issues as when transaction is getting started it tries to fetch connection from datasource which is not present and throws communicationslinkfailure exception
How can I mock datasource in this case ? or any other alternative to solve the issue is also appreciated ?
Below is a snippet from the camle-osgi example. I can obtain the camel context but how do I get the original spring application context? Or how am I supposed to get a reference to "mybean"?
MyRouteBuilder.java:
public class MyRouteBuilder extends RouteBuilder {
public static void main(String[] args) throws Exception{
new Main().run(args);
}
public void configure() {
// set up the transform bean
ModelCamelContext mc = getContext();//ok, I can get the camel context fine
//but how to get the spring context to get to "mybean"???
//set up routes
}
}
beans.xml:
<beans>
<camel:camelContext xmlns="http://camel.apache.org/schema/spring">
<package>org.apache.servicemix.examples.camel</package>
-----
</route>
</camel:camelContext>
<bean id="mybean" class="myclass"/>
</beans>
You should not use the spring context directly. Instead use the spring features to inject the beans you need.
Define the routebuilder as a bean in the spring context and use a setter and to inject myBean.
Keep the auto discovery and use annotations like #Autowired in the routebuilder to inject mybean.
A third option is to use getContext().getRegistry(). The registry allows to access all beans of the spring context by name or by type.
It would not be camel if we are already out of options :-)
So another options is to use the bean component of camel to access beans from the spring context: http://camel.apache.org/bean.html
I think I've read every question and answer on Spring and autowiring a servlet, both here and at springsource.org, and I still can't get it working.
All I want to do is have the datasource automatically set in my servlets. I understand that the container creates the servlet and not Spring.
Here is code from my test servlet:
package mypackage.servlets;
imports go here...
#Service
public class TestServlet extends HttpServlet
{
private JdbcTemplate _jt;
#Autowired
public void setDataSource(DataSource dataSource)
{
_jt = new JdbcTemplate(dataSource);
}
etc etc
In my applicationContext.xml I have:
<context:annotation-config />
<context:component-scan base-package="mypackage.servlets />
<import resource="datasource.xml" />
and in my datasource.xml:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/db" />
If I can't get this working I'll just use WebApplicationContextUtils in the servlet's init method but I'd really like to make this work after all the reading I've been doing.
I'm using Spring 3, Java 1.6.
Thanks,
Paul
You need to replace your Servlets by Spring MVC contollers. Because Spring will not inject anything the classes (servlets) created by someone else then Spring itselfe (except #Configurable).
(To get an very simple example, take a look at the STS Spring Template Project: MVC).
What I wanted to do was get a DataSource reference in my Servlet for free, i.e. not calling a static getDatasource method on some class.
Here's what I learned and how I got it working:
Servlets cannot be configured or autowired by Spring. Servlets are created before Spring's app context is loaded. See issue SPR-7801: https://jira.springsource.org/browse/SPR-7801
What I did was create a DataSource in my applicationContext.xml and export that as a property:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/db" />
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="myDatasource">
<ref bean="dataSource"/>
</entry>
</map>
</property>
</bean>
In my servlet's init method I read the property:
public void init(ServletConfig config)
{
Object obj = config.getServletContext().getAttribute("myDatasource");
setDataSource((DataSource)obj);
}
public void setDataSource(DataSource datasource)
{
// do something here with datasource, like
// store it or make a JdbcTemplate out of it
}
If I'd been using DAOs instead of hitting the database from the servlets it would have been easy to wire them up for #Autowired by marking them #Configurable, and also be able to use #Transactional and other Spring goodies.