I am trying to integrate HA-JDBC with Spring Boot JPA. Can any one help to integrate Ha-Jdbc with spring boot JPA,
import java.util.Arrays;
import javax.naming.NamingException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import net.sf.hajdbc.SimpleDatabaseClusterConfigurationFactory;
import net.sf.hajdbc.cache.simple.SimpleDatabaseMetaDataCacheFactory;
import net.sf.hajdbc.dialect.oracle.OracleDialectFactory;
import net.sf.hajdbc.distributed.jgroups.JGroupsCommandDispatcherFactory;
import net.sf.hajdbc.sql.DataSource;
import net.sf.hajdbc.sql.DataSourceDatabase;
import net.sf.hajdbc.sql.DataSourceDatabaseClusterConfiguration;
import net.sf.hajdbc.state.simple.SimpleStateManagerFactory;
#Configuration
public class HAJdbcConfig
{
#Bean
public DataSourceDatabase db1()
{
DataSourceDatabase db1 = new DataSourceDatabase();
db1.setId("db1");
db1.setLocation("database url");
db1.setUser("username");
db1.setPassword("password");
return db1;
}
#Bean
public DataSourceDatabase db2()
{
DataSourceDatabase db1 = new DataSourceDatabase();
db1.setId("db1");
db1.setLocation("database url");
db1.setUser("username");
db1.setPassword("password");
return db1;
}
#Bean
public DataSourceDatabaseClusterConfiguration config() throws NamingException
{
DataSourceDatabaseClusterConfiguration config = new DataSourceDatabaseClusterConfiguration();
config.setDatabases(Arrays.asList(db1(), db2()));
config.setDialectFactory(new OracleDialectFactory());
config.setDatabaseMetaDataCacheFactory(new SimpleDatabaseMetaDataCacheFactory());
SimpleStateManagerFactory state = new SimpleStateManagerFactory();
config.setStateManagerFactory(state);
config.setDispatcherFactory(new JGroupsCommandDispatcherFactory());
return config;
}
#Bean
public javax.sql.DataSource primaryDataSource() throws NamingException
{
DataSource ds = new DataSource();
ds.setCluster("mycluster");
//ds.setConfig("ha-jdbc-mycluster.xml");
ds.setConfigurationFactory(
new SimpleDatabaseClusterConfigurationFactory<javax.sql.DataSource, DataSourceDatabase>(config()));
return ds;
}
}
Error retrieving database meta-data; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Failed to perform naming lookup of jdbc:oracle:thin:#//localhost:1521/orcl
I don't have much experience with HA-JDBC, but maybe I can put you in track. You never declare the Driver and the lookup is trying to create an Oracle URL connection (dbc:oracle:thin:#//localhost:1521/orcl).
I hope it gives you an idea of where to look.
I think there is something wrong with your the jdbc url.
The format is jdbc:oracle:<drivertype>:#<database> in your case
jdbc:oracle:thin:#localhost:1521/orcl
without // before the host.
Can you use the service name for the database? The simple connection URL is jdbc:oracle:thin:#myhost:1521/myorcldbservicename. Also, you can check out the sample SpringBootApp for an example.
Related
I tried to testing my Dao class but it return this error for the class DbConnection:
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or in an application resource file: java.naming.factory.initial
at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:691)
at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
at java.naming/javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:342)
at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
at model.DbConnection.(DbConnection.java:16)
at model.DbConnection.getInstance(DbConnection.java:30)
at model.ProfileManager.ReturnPatientByKey(ProfileManager.java:27)
at model.ProfileManagerTest.testReturnPatientByKey(ProfileManagerTest.java:32)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
....
my DbConnection class:
package model;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DbConnection {
private DbConnection() {
Context ctx;
try {
ctx = new InitialContext();
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CheckUpDb");
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException {
return ds.getConnection();
}
public static DbConnection getInstance () {
if(db==null) {
return new DbConnection();
}
else {
return db;
}
}
private static DataSource ds;
private static DbConnection db;
}
Database connection works in the web application, only the testing return this error.
I don't think the problem si my class ProfileManager because it is only a testing example:
import static org.junit.Assert.assertTrue;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import model.Bean.PatientBean;
class ProfileManagerTest{
private ProfileManager pm;
String fiscal_code;
String user_password;
PatientBean patient;
#BeforeEach
void setUp() throws Exception {
this.pm = new ProfileManager();
fiscal_code = "aaa";
user_password = "bbb";
patient = mock(PatientBean.class);
}
#AfterEach
void tearDown() throws Exception {
}
#Test
void testReturnPatientByKey() {
patient = (PatientBean) pm.ReturnPatientByKey(fiscal_code, user_password);
assertTrue(true);
}
}
Database connection works in the web application, only the testing return this error.
That's most likely because you have the datasource declared in the server configuration and the server is providing your web app with one, but you don't have the same done in your test.
Do a search in your server files an you will probably discover something like this, or similar, depending on what server you use:
<Resource name="jdbc/CheckUpDb"
driverClassName="..."
type="..."
url="..."
username="..."
password="..."
/>
This is a way to configure a datasource using JNDI. When your web application runs, the server will provide you with this resource by name. This is what ctx.lookup("java:comp/env/jdbc/CheckUpDb"); does. It asks the server to give it that resource.
But when you run your unit tests, you run outside the server environment. That means that any resource you defined in the server (using context.xml for example) doesn't exist when you run your tests. In your tests you have to provide a datasource and make it available to your JNDI context so that this line of code then works:
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CheckUpDb");
The following post should give you the necessary details to set up your JNDI data source for your test: Setting up JNDI Datasource in jUnit
You will see that the examples there make use of a library called Simple-Jndi that they use to provide a JNDI context and configure it to include the datasource that the tests then try to retrieve by name. You can use any JNDI provider, but you must set up the datasource for your test yourself (inside #BeforeEach or #BeforeAll) because when running unit tests, you don't have the tomcat server doing this for you.
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 6 years ago.
I made a form with Spring MVC. I want use it to fill data in my databases.
I use a DAO. With a sysout I show data in the consol but it's impossible to execute the query.
package controlleurs;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
#Repository("RepertoryDAO")
public class RepertoryDAO {
private JdbcTemplate myJdbc;
public RepertoryDAO(){
}
#Autowired
public void setMonJdbc(DataSource ds) {
//this.JdbcTemplate = new JdbcTemplate(ds);
this.myJdbc = new JdbcTemplate(ds);
}
//Display data
public List<Repertory> getRepetories(){
return myJdbc.query("select*from main",new RowMapper<Repertory>(){
public Repertory mapRow(ResultSet rs, int rowNum1)
throws SQLException {
Repertory rp=new Repertory();
rp.setId(rs.getInt("id"));
rp.setName(rs.getString("name"));
return rp;
}
});
}
//Add a repertory in database
public void addRepertory(String name, String url, int bl, int noFree, String topic){
String backlinkRequired=Integer.toString(bl);
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("name", name);
System.out.println(name);
params.addValue("url", url);
System.out.println(url);
params.addValue("lienRetour", backlinkRequired);
System.out.println(backlinkRequired);
params.addValue("payant", noFree);
System.out.println(noFree);
params.addValue("topic", topic);
System.out.println(topic);
System.out.println("jdbc"+ getMonJdbc().toString());
this.myJdbc.update("insert into main (name,url,lienRetour,payant,topic) values (:name,:url,:lienRetour,:payant,:topic)",params);
}
public JdbcTemplate getMonJdbc() {
return this.myJdbc;
}
This line give me anything in the console.
System.out.println("jdbc"+ getMonJdbc().toString());
The console display this error:
déc. 28, 2016 2:58:32 PM org.apache.catalina.core.StandardWrapperValve
invoke
GRAVE: Servlet.service() for servlet [MyServletSpring] in context with path [/monProjetSpring] threw exception [Request processing
failed; nested exception is java.lang.NullPointerException] with root
cause
java.lang.NullPointerException
at controlleurs.RepertoryDAO.addRepertory(RepertoryDAO.java:65)
at controlleurs.NewDirectory.directoryRegistered(NewDirectory.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
Thanks for your help.
It seems to be a basic Spring issue.
First, look if you've got a dataSource registered, for me the autowired annotation just try to inject the dataSource parameter. If it's right, you could try to define a jdbcTemplate bean in your xml config file with the datasource as properties.
Then you can put your #Autowired just above your jdbcTemplate definition in your DAO class.
This may not be the way you want but it could work easily.
I am using Apache Derby and have the following code:
DBConnectionFactory.java
package edu.unsw.comp9321.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import edu.unsw.comp9321.common.DataSourceException;
import edu.unsw.comp9321.common.ServiceLocatorException;
// This class looks up the database via JNDI and returns a connection to the DAO Implementation class
public class DBConnectionFactory {
static Logger logger = Logger.getLogger(DBConnectionFactory.class.getName());
private static DBConnectionFactory factory = null;
private DataSource ds = null;
private InitialContext ctx;
private Context subctx;
private DBConnectionFactory() throws ServiceLocatorException{
try{
ctx = new InitialContext();
ds = (DataSource) ctx.lookup("java:comp/env/jdbc/cs9321");
logger.info("Database found:"+ds.toString());
}catch(NamingException e){
logger.severe("Cannot find context, throwing exception"+e.getMessage());
e.printStackTrace();
throw new ServiceLocatorException();
}
}
public DataSource getDataSource(){
return ds;
}
public static Connection getConnection() throws ServiceLocatorException, SQLException{
if(factory==null)
factory = new DBConnectionFactory();
Connection conn = factory.getDataSource().getConnection();
return conn;
}
}
The error seems to occur here:
ds = (DataSource) ctx.lookup("java:comp/env/jdbc/cs9321");
I read that this may occur if derbyclient.jar is not in the build path. However, I have already added this jar to the build path.
Would anyone have any suggestions as to what I can do?
Thanks.
You're missing a couple of jars, add this two and everything should be ok:
commons-dbcp-1.4.jar
commons-pool-1.6.jar
Hope that helps!
Cheers
I have the following class for obtaining a JDBC connection:
package util;
import java.sql.Connection;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class OracleConnection implements AutoCloseable{
private final String oracle_DS_CTX = "java:jboss/oracleDS";
// #Resource(name="java:jboss/oracleDS")
// private DataSource ds; //doesn't work
private Connection _conn;
public OracleConnection() throws SQLException, NamingException{
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(oracle_DS_CTX);
_conn = ds.getConnection();
}
#Override
public void close() throws Exception {
if(_conn != null){
_conn.close();
}
}
public Connection getConnection() throws SQLException {
return _conn;
}
}
I have a problem using the #Resource annotation. Datasource obtained via InitialContext works without any problems but I am not sure what string should I put into resource name (commented out in my code).
I have tried:
#Resource(name="java:jboss/oracleDS")
#Resource(name="oracleDS")
AS is JBOSS AS7
What name did you define in your standalone.xml?
That is the name you need to define in your #Resource
But there's a little trick, you need to set it in the lookup property instead of name.
Here's an example, let's assume my DS jndi is java:jboss/ExampleDS.
#Resource(lookup = "java:jboss/ExampleDS")
private DataSource dataSource;
I'm creating a web app using NetBeans and Tomcat 7 and I wanted to create my first connection pool.
I've followed all the steps in the tomcat documentation here:
http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html
But in my application I'll have many DAO objects with many different methods each, so I'd like to avoid writing the code for looking up the datasource and getting a connection in each and every method that access to the DB, so I've created a class to centralize this operation and return a connection to the different DAO objects.
You can see the code below, but as I said it's my first time wth this, so I'm not sure... does this make sense for you? is there a better way to do something like that? or it's just better to write this code in each method?
And if this does make sense, could I use the Context or even also the DataSource as static attributes to avoid continuous lookups?
Thanks very much!
My ConnectionPool class:
package dao.mysql;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.tomcat.jdbc.pool.DataSource;
public class ConnectionPool {
public static Connection getConnection() {
Connection connection = null;
try {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource)envCtx.lookup("jdbc/EmployeeDB");
connection = ds.getConnection();
} catch (SQLException ex) {
Logger.getLogger(ConnectionPool.class.getName()).log(Level.SEVERE, null, ex);
} catch (NamingException ex) {
Logger.getLogger(ConnectionPool.class.getName()).log(Level.SEVERE, null, ex);
}
return connection;
}
}
You can use JDBC Connection Pool as a singleton bean as described here in this article.