I have a java project that implements some APIs, in Eclipse.
I have db.java file that enables the communication with the MySQL database.
Instead of have the MySQL credentials in a java file, I would like to have them in /META-INF/context.xml file.
Do you know how to do this?
This is my current code:
public class db {
private String userName = null;
private String password = null;
private String dbName = null;
private String db_connect_string = null;
public db() {
this.db_connect_string = "jdbc:mysql://localhost/mydb";
this.dbName = "name";
this.userName = "uname";
this.password = "pass";
}
protected Connection getDBMySQLCon() {
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
return DriverManager.getConnection(this.db_connect_string+"?useSSL=false", this.userName, this.password);
} catch (ClassNotFoundException | SQLException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
Instead of an XML file, you can have a properties file, that has the required information. Problem with XML file is that you will have to choose an XML parser and work with it.
If you want to go ahead with properties file you can consider the following snippet.
public void setProp() throws Exception{
FileReader reader=new FileReader("db.properties");
Properties p=new Properties();
p.load(reader);
// you can get values you want as properties using
this.db_connect_string = p.getProperty("db_connect_string");
this.dbName = p.getProperty("dbName");
}
And your file structure should be something like
db_connect_string=connection.string
dbName=name
userName=uname
password=pass
This is part of the environment of the container.
/META-INF/context.xml
The context.xml overides the tomcate context entry.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- Specify a JDBC datasource -->
<Resource name="jdbc/mydatabase"
auth="Container"
type="javax.sql.DataSource"
username="YOUR_USERNAME"
password="YOUR_PASSWORD"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://mysql.metawerx.net:3306/YOUR_DATABASE_NAME?
autoReconnect=true"
validationQuery="select 1"
maxActive="10"
maxIdle="4"/>
</Context>
// Get DataSource
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mydatabase");
// Get Connection and Statement
Connection c = ds.getConnection();
Statement s = c.createStatement();
Related
I have settings in the context.xml which contain the information for the connection of my database
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<Resource
name="jdbc/*(my username)*"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
auth="Container"
type="javax.sql.DataSource"
removeAbandoned="true"
removeAbandonedTimeout="30"
maxACtive="100"
maxIdle="30"
maxWait="10000"
username= *(my username)*
password= *(my password)*
driverClassName="com.ibm.db2.jcc.DB2Driver"
url="jdbc:db2://(my server host):50000/*(my username)*">
</Resource>
</Context>
While for the Connection Pool I created a class to initiate and to connect it to the database. The error begins in the method of getConnection(). The way the error is NullPointerException in the return of the datasource.getConnection()
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class ConnectionPool {
private static ConnectionPool pool = null;
private static DataSource dataSource = null;
private ConnectionPool() {
try {
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup("java:/comp/env/jdbc/COMPANY");
System.out.print(dataSource);
} catch (NamingException e) {
System.out.println(e);
}
}
public static synchronized ConnectionPool getInstance() {
if (pool == null) {
pool = new ConnectionPool();
}
return pool;
}
public Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
System.out.println(e);
return null;
}
}
public void freeConnection(Connection c) {
try {
c.close();
} catch (SQLException e) {
System.out.println(e);
}
}
}
I tested the database connection with Eclipse's Perspective Database Development and I was able to connect and done all the queries.
In addition, it gives me this error in output
SEVERE: Unable to create initial connections of pool.
java.sql.SQLException: No suitable driver found for jdbc:db2://db2.cecsresearch.org:50000/(my username)
Although I have the jar library files in the lib folder and in the classpath.
Please download the DB2 Java driver from https://artifacts.alfresco.com/nexus/content/repositories/public/com/ibm/db2/jcc/db2jcc4/10.1/db2jcc4-10.1.jar and add it to your tomcat/lib directory. Then restart Tomcat and you should be good to go !!
The nullpointer is simply caused by the following problem:
java.sql.SQLException: No suitable driver found for jdbc:db2://db2.cecsresearch.org:50000/(my username)
Putting your database driver in $CATALINA_HOME/lib should fix the problem.
For more info, check the docs.
driverClassName (String) The fully qualified Java class name of the
JDBC driver to be used. The driver has to be accessible from the same
classloader as tomcat-jdbc.jar
You can also check the official jndi-datasource examples.
I build webApp . When I run app from Eclipse everything work OK. Now I build WAR file, put in tomcat root, andI want to all my system property put in context.xml in tomcat. Then, when app is start, that values from context.xml is read and use in app.
Problem is I don't know how to get values from context.xml in my webapp?
This is context:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="" docBase="fileupload.war" privileged="true" antiResourceLocking="false" antiJARLocking="false">
<Resource
mail.smtp_server = "127.0.0.1"
mail.smtp_username = "no-reply#gmail.rs"
mail.mailTo = "test#gmail.com"
rootFolder = "D:/project/"
rootFolderBackup = "D:/project/Backup/"
/>
Here I want to get a values from context.xml :
#RequestMapping(value="api/files")
public class FileController {
final static Logger logger = Logger.getLogger(FileController.class);
#Autowired
ApplicationContext applicationContext;
private String mailTo;
private String sender;
private String rootFolder = "";
private String rootFolderBackup = "";
#PostConstruct
private void init(){
try {
InitialContext ic = new InitialContext();
Context xmlContext = (Context) ic.lookup("java:comp/env"); // thats everything from the context.xml and from the global configuration
DataSource myDatasource = (DataSource) xmlContext.lookup("rootFolder");
} catch (NamingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
This is common error :
Name [rootFolder] is not bound in this Context. Unable to find [rootFolder].
I try few solution which I found on web but not working...
My context.xml file is in C:\tomcat-7.0\conf\Catalina\localhost , and war file is in C:\tomcat-7.0\webapps
If you want to define application properties you should probably use Environment variables instead. Ex you can set a variable in any context.xml like this:
<Environment name="PROPERTIES_FILE" override="false" type="java.lang.String" value="C:/path/to/propfile.properties" />
<!--define more variables here -->
and then in your application you can read those environment properties from JNDI like this.
initCtx = new InitialContext();
String path = (String) initCtx.lookup("java:comp/env/PROPERTIES_FILE");
// fetch more variables here
Further reading:
https://tomcat.apache.org/tomcat-8.0-doc/config/context.html#Environment_Entries
https://tomcat.apache.org/tomcat-8.0-doc/jndi-resources-howto.html
In a Hadoop MapReduce program, I am trying to read JDBC connection details from connection.properties file, that is also in proper classpath.
Code:
public synchronized Connection getConnection() {
return getDetails(); // inside try catch block
}
public Connection getDetails() throws SQLException, IOException {
Properties props = new Properties();
FileInputStream in = new FileInputStream("connection.properties");
props.load(in);
in.close();
String drivers = props.getProperty("jdbc.drivers");
if (drivers != null) {
System.setProperty("jdbc.drivers",drivers);
}
String url = props.getProperty("jdbc.url");
String username = props.getProperty("jdbc.username");
String password = props.getProperty("jdbc.password");
return DriverManager.getConnection(url, username, password);
}
But when running my driver main program it gives an error:
java.io.FileNotFoundException: connection.properties (No such file or directory)
Any idea?
In order to run the MapReduce that uses properties file, you need to package it with your code, and instead of using the traditional reading the file streams from local system, you can read it from the jar you already built
reading properties from jar:
InputStream stream = this.getClass().getResourceAsStream("foo.properties"))
I'v added custom jndi-resource factory to my tomcat (jndi-resource for ConnectionFactory of an embedded hornetq). My resource needs some config files; I put them in ${catalina_home}/hornetq folder. I have a test-web-app that uses this resource in tomcat start-up. In tomcat start-up, When test-web-app wants to use my resource, the resource wants to lock config files but it can't, and it throws `OverlappingFileLockException:
java.nio.channels.OverlappingFileLockException
at sun.nio.ch.SharedFileLockTable.checkList(FileLockTable.java:255)
at sun.nio.ch.SharedFileLockTable.add(FileLockTable.java:152)
at sun.nio.ch.FileChannelImpl.tryLock(FileChannelImpl.java:1056)
at org.hornetq.core.server.impl.FileLockNodeManager.tryLock(FileLockNodeManager.java:266)
at org.hornetq.core.server.impl.FileLockNodeManager.isBackupLive(FileLockNodeManager.java:82)
at org.hornetq.core.server.impl.HornetQServerImpl$SharedStoreLiveActivation.run(HornetQServerImpl.java:2161)
at org.hornetq.core.server.impl.HornetQServerImpl.start(HornetQServerImpl.java:450)
at org.hornetq.jms.server.impl.JMSServerManagerImpl.start(JMSServerManagerImpl.java:485)
at org.hornetq.jms.server.embedded.EmbeddedJMS.start(EmbeddedJMS.java:115)
at ...
Is it possible to disable file locking (files in ${catalina_home}/hornetq directory) in tomcat or OS?
Update:
My jndi-resource in context.xml file in tomcat (A connection factory with name: /ConnectionFactory is defined in hornetq-jms.xml):
<Resource name="jms/ConnectionFactory" auth="Container"
type="javax.jms.ConnectionFactory"
factory="com.wise.jms.hornetq.embedded.HornetqConnectionFactoryBuilder"
cf-name="/ConnectionFactory" singletone="true"/>
My factory class: HornetqConnectionFactoryBuilder. I put the jar containing this class in ${catalina_home}/lib directory (The embedded hornetq will be started in the first getObjectInstance method call):
public class HornetqConnectionFactoryBuilder implements ObjectFactory{
private EmbeddedJMS embeddedJMS;
private static final String ConnectionFactoryName = "cf-name";
private static final String HornetqConfigDirectoryPath = getCatalinaHomePath() + "/conf/hornetq/";
private static final String JmsConfigFilePath = HornetqConfigDirectoryPath + "hornetq-jms.xml";
private static final String HornetqConfigFilePath = HornetqConfigDirectoryPath + "hornetq-configuration.xml";
#Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception{
Properties properties = initProperties((Reference) obj);
validateProperties(properties);
initHornetq();
String connectionFactoryJndiName = (String) properties.get(ConnectionFactoryName);
return embeddedJMS.lookup(connectionFactoryJndiName);
}
private synchronized void initHornetq() throws Exception{
if (embeddedJMS == null){
embeddedJMS = new EmbeddedJMS();
embeddedJMS.setJmsConfigResourcePath(JmsConfigFilePath);
embeddedJMS.setConfigResourcePath(HornetqConfigFilePath);
embeddedJMS.start();
}
}
private Properties initProperties(Reference reference) throws IOException{
Enumeration<RefAddr> addresses = reference.getAll();
Properties properties = new Properties();
while (addresses.hasMoreElements()) {
RefAddr address = addresses.nextElement();
String type = address.getType();
String value = (String) address.getContent();
properties.put(type, value);
}
return properties;
}
private void validateProperties(Properties properties){
validateSingleProperty(properties, ConnectionFactoryName);
}
private static String getCatalinaHomePath(){
String catalinaHome = System.getenv("CATALINA_HOME");
if (catalinaHome == null){
throw new IllegalArgumentException("CATALINA_HOME environment variable should be set");
}
return "file:///" + catalinaHome.replaceAll("\\\\", "/");
}
private static void validateSingleProperty(Properties properties, String propertyName){
if (!properties.containsKey(propertyName)){
throw new IllegalArgumentException(propertyName + " property should be set.");
}
}
}
My test-web-app Test Class (test method will be lunch in test-web-app start-up):
public class Test{
private ConnectionFactory connectionFactory;
public Test() throws NamingException{
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
connectionFactory = (ConnectionFactory) envCtx.lookup("jms/ConnectionFactory");
}
public void test() throws JMSException{
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(true,Session.SESSION_TRANSACTED);
Queue queue = session.createQueue("testQueue");
MessageProducer messageProducer = session.createProducer(queue);
MessageConsumer messageConsumer = session.createConsumer(queue);
TextMessage message1 = session.createTextMessage("This is a text message1");
messageProducer.send(message1);
session.commit();
TextMessage receivedMessage = (TextMessage) messageConsumer.receive(5000);
session.commit();
System.out.println("Message1 received after receive commit: " + receivedMessage.getText());
}
public void setConnectionFactory(ConnectionFactory connectionFactory){
this.connectionFactory = connectionFactory;
}
}
Note: when i put (hornetq) config files in the jar class-path, i have no problem and everything is fine!! (tomcat: 6, hornetq: 2.4.0.Final, OS: windows 7)
Do you have other deployments in the Tomcat?
There is very well chance that once you restart tomcat, some other project gets deployed first which uses the file in the lib folder.
Try deploying it in a fresh tomcat installation or remove other folders from the webapps folder in Tomcat.
I am having this error on Netbeans 7.2, it says that ClassNotFoundexception and InstantationException. I am really stuck on this matter. Kindly help me.
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String driver = "com.mysql.jdbc.Driver";
con = null;
String username = "";
String password = "";
Class.forName("com.mysql.jdbc.Driver").newInstance();
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbName", "root", "password");
Statement st = con.createStatement();
ResultSet mar = st.executeQuery("SELECT * FROM table");
Gson gson = new GsonBuilder().create();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
} catch (SQLException e) {
String message = e.getMessage();
}
What about this simple way?!
java.sql.Driver d=new com.mysql.jdbc.Driver();
I also wondered why do you connect to database with such this way?! It's better let server manage it.
First config the context.xml (if you are using tomcat) like this:
<context>
<Resource name="_ds" auth="Container" type="javax.sql.DataSource"
maxActive="128" maxIdle="32" username="_admin" password="qwerty" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/dbname"/>
</context>
Then, simple get a connection from this resource in servlet/etc, like this:
public void init() {
try {
_ds = (DataSource) InitialContext.lookup("java:/comp/env/_ds");
} catch (Exception ex) {
}
}
private javax.sql.DataSource _ds;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
try {
/*String driver = "com.mysql.jdbc.Driver";
con = null;
String username = "";
String password = "";
Class.forName("com.mysql.jdbc.Driver").newInstance();
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbName", "root", "password");*/
Connection con=_ds.getConnection();
Statement st = con.createStatement();
ResultSet mar = st.executeQuery("SELECT * FROM table");
Gson gson = new GsonBuilder().create();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
con.close();
} catch (SQLException e) {
String message = e.getMessage();
}
By the way, don't forget to compy the MySQL JDBC driver jar-file in <CATALINA_BASE>/lib folder.
All you need is Class.forName("com.mysql.jdbc.Driver")
This acts like class loader and load your driver class for you. For that you need to add the corresponding jar file(which has the driver implementation). So download and add mysql-connector.jar in your class path.
Note : If you are using Java 7 then there is no need to even add the Class.forName("com.mysql.jdbc.Driver") statement.Automatic Resource Management (ARM) is added in JDBC 4.1 which comes by default in Java 7.
You might want to solve a bigger problem. You ought not enter configuration data such as database connection information directly in your servlet.
Are you using Tomcat? You can simply use JNDI. You will be able to change database details and drivers without having to recompile your servlet.
Here is the Tomcat 7.0 JNDI Datasource HOW-TO shows various ways in which you can get a Connection to your database.
On that page, you have a code example of how to get a Connection (Oracle 8i, 9i & 10g -> Part 3), and how to write a MySQL specific configuration.
Make sure to download a correct MySQL jar and place it in your Tomcat's lib/ directory (or alternatively your WAR's WEB-INF/lib).
You need to add mysqlconnector.jar file found here: ( http://dev.mysql.com/downloads/connector/j/ ) into your lib folder of your project. Include it with your project and then you can access your connection with database.
Add that jar into the buildpath.