I have an external MySQL server that's set up and working fine. I created a database connection in Eclipse and can view the database in the Data Source Explorer tab.
Now, I have a servlet that needs to access that database. How do I do it? Is there a way to reference that database connection created in the data source explorer, or do I have to define everything twice?
Also, what's the best way to open the connection? I've got the mysql-connector-java-5.1.11-bin.jar file included, and I've found two methods that work:
MysqlDataSource d = new MysqlDataSource();
d.setUser("user");
d.setPassword("pass");
d.setServerName("hostname.com");
d.setDatabaseName("db");
Connection c = d.getConnection();
and
Connection c = DriverManager.getConnection("jdbc:mysql://hostname.com/db","user","pass");
Neither is optimal, because first of all, they both use hard-coded strings for everything. This is a Java EE web app project, so is there a good place to put connection data? Or is there a way to forgo all that and just use the connection in the data source explorer?
A common practice is to configure this as a DataSource in the servlet container in question. It will provide you connection pooling facilities which will greatly improve performance. Also a common practice is to externalize the raw settings in some configuration file which is been placed in the classpath.
In case you're using Tomcat as servletcontainer, you need to configure the datasource as per its JNDI documentation. You'll see that there are several ways. Easiest way is to create a /META-INF/context.xml in the webcontent of your dynamic web project (to be clear, the /META-INF is at the same level as the /WEB-INF of the webapp) and fill it with something like:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource
name="jdbc/db" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
url="jdbc:mysql://hostname.com/db"
driverClassName="com.mysql.jdbc.Driver"
username="user" password="pass"
/>
</Context>
This roughly means that Tomcat server should create a datasource with the JNDI name jdbc/db with a maximum of 100 active connections, a maximum of 30 idle connections and a maximum wait time of 10000 milliseconds before a connection should be returned from your application (actually: closed by your application, so your application has 10 seconds time between acquiring the connection and closing the connection). The remnant of the settings should be familiar and self-explaining enough to you; those are the JDBC settings.
Finally in your web project, edit the file /WEB-INF/web.xml to add the following entry:
<resource-env-ref>
<resource-env-ref-name>jdbc/db</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
</resource-env-ref>
This roughly means that the webapplication should use the server-provided datasource with the name jdbc/db.
Then change your connection manager to something like this:
private DataSource dataSource;
public Database(String jndiname) {
try {
dataSource = (DataSource) new InitialContext().lookup("java:comp/env/" + jndiname);
} catch (NamingException e) {
// Handle error that it's not configured in JNDI.
throw new IllegalStateException(jndiname + " is missing in JNDI!", e);
}
}
public Connection getConnection() {
return dataSource.getConnection();
}
..and replace all Class.forName(driver) calls by new Database("jdbc/db") and replace all DriverManager.getConnection() calls by database.getConnection(). You can if necessary obtain the value jdbc/db from some config file (Properties file?).
Alternatively, inject the DataSource via the #Resource annotation inside a container managed artifact, such as a #WebServlet servlet class:
#Resource(name="jdbc/db")
private DataSource dataSource;
That should be it. Just deploy your webapplication with the above changes and run it. Don't forget to place the database JDBC driver in the Tomcat/lib or to add its path to the shared.loader property of Tomcat/conf/catalina.properties, because the responsibility of loading the JDBC driver is now moved from the webapplication to the server. For more hints and other basic JDBC/JNDI examples you may find this article useful as well.
See also:
How to install JDBC driver in Eclipse web project without facing java.lang.ClassNotFoundexception
Where do I have to place the JDBC driver for Tomcat's connection pool?
Is it safe to use a static java.sql.Connection instance in a multithreaded system?
Show JDBC ResultSet in HTML in JSP page using MVC and DAO pattern
How to retrieve and display images from a database in a JSP page?
You could set up a data source in whatever app server you're deploying your WAR to and fetch a reference to it with JNDI. Or you could package your WAR in an EAR and define the data source in the EAR's data-sources.xml file (and fetch a reference to it with JNDI).
Related
I'm running my project in wildfly in a container in openshift. And I'm trying to add hazelcast-kubernetes plugin( from https://github.com/hazelcast/hazelcast-kubernetes) to my project for DNS lookup. It seems the plugin's DNS lookup doesn't work at all.
Inside the Openshift's logs, it shows the Kubernetes Discovery SPI activated and wildfly starts successfully.
I've already set my hazelcast following the instruction:
this.config.setProperty("hazelcast.discovery.enabled", "true");
this.config.setProperty("hazelcast.rest.enabled","true");
final JoinConfig joinConfig = networkConfig.getJoin();
joinConfig.getMulticastConfig().setEnabled(false);
joinConfig.getTcpIpConfig().setEnabled(false);
final HazelcastKubernetesDiscoveryStrategyFactory factory = new HazelcastKubernetesDiscoveryStrategyFactory();
final DiscoveryStrategyConfig strategyConfig = new DiscoveryStrategyConfig(factory);
strategyConfig.addProperty("service-dns", "kubernetes.default.svc.cluster.local");
strategyConfig.addProperty("service-dns-timeout", "10");
Did I miss something? Any advice would be appreciate.
I am working on a Notification Service using IBM MQ messaging provider with JBoss eap 6.1 environment. I am successfully able to send messages via MQ JCA provider rar i.e. wmq.jmsra.rar file. However on consumer part my current configuration looks like this
#MessageDriven(
activationConfig = {
#ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
#ActivationConfigProperty(propertyName="destination", propertyValue="F2.QUEUE"),
#ActivationConfigProperty(propertyName="providerAdapterJNDI", propertyValue="java:jboss/jms/TopicFactory"),
#ActivationConfigProperty(propertyName="queueManager", propertyValue="TOPIC.MANAGER"),
#ActivationConfigProperty(propertyName="hostName", propertyValue="10.239.217.242"),
#ActivationConfigProperty(propertyName="userName", propertyValue="root"),
#ActivationConfigProperty(propertyName = "channel", propertyValue = "TOPIC.CHANNEL"),
#ActivationConfigProperty(propertyName = "port", propertyValue = "1422")
})
My problem is that consumer of this service does not want to add any port numbers, hostName, queueManager properties in these beans. Also they do not want to use ejb-jar.xml to externalize these configs. I have researched and found that we can add a domain IBM Message Driven Bean but with no success. Any suggestions on what I can do here to externalize all these configurations ?
EDIT: Adding --> The JCA resource adapter is deployed at consumer end if it makes it any easier.
Thanks
You can actually externalize an MDBs activation spec properties to the server configuration file.
Create the ejb-jar.xml file, but do not put the actual value in the file, use a property placeholder:
<activation-config-property>
<activation-config-property-name>hostName</activation-config-property-name>
<activation-config-property-value>${wmq.host}</activation-config-property-value>
</activation-config-property>
Do this for all of the desired properties.
Ensure that property replacement for Java EE spec files (ejb-jar.xml, in this case) is enabled in the server configuration file:
<subsystem xmlns="urn:jboss:domain:ee:1.2">
<spec-descriptor-property-replacement>true</spec-descriptor-property-replacement>
Then, in the server configuration file, provide values for your properties:
<system-properties>
<property name="wmq.host" value="10.0.0.150"/>
Once your MDBs are packaged, you will not need to change any of the files in the MDB jar - just provide the properties in the server configuration.
you can avoid to add host name, port number and so on in MDB, you just want to define destinationType in MDB, and rest of the thing u can configure in your application server, like Activation Specification, Queues and Queue Connection Factories.
I have done the same thing but i used IBM Websphere Application Server.
API Store is throwing errors when I try to create or edit an application
java.sql.SQLException: Can't call commit when autocommit=true
I've added the setting of
init-command='set autocommit=0'
to the my.cnf file
I've also added the flag:
?relaxAutoCommit=true
to the connection string but to no avail. I continue to get this error.
I am using the same mysql database for both the WSO2_CARBON_DB and teh WSO2AM_DB plus I have a single publisher node and two separate store nodes all pointing to the same mysql datasource.
I notice the application edit is saved (or the new application is created) but the exception is still thrown in the console and an error message appears in the user interface (as per the error at the top of this question).
Is there some other setting, within the WSO2 conf files that I have to tweak in order to get this to work properly?
Add both autoReconnect and relaxAutoCommit flags to the jdbc url of your defined "WSO2AM_DB" datasource in master-datasources.xml file. This will resolve your issue.
<configuration>
<url>jdbc:mysql://localhost:3306/AM_DB?autoReconnect=true&relaxAutoCommit=true</url>
<username>xxxx</username>
<;password>xxxxx</password>
EDIT: I updated the url to reflect the correct syntax for escaping the ampersand.
just for the sake of completeness, the JDBC URL shoud be
jdbc:mysql://localhost:3306/WSO2CARBON_DB?autoReconnect=true&relaxAutoCommit=true
I've written a GWT web app which is hosted on an external openSUSE server. I use Google's GWT RPC to communicate with the server and send data from my client to the server where a MySQL database gets updated. Everything works perfectly fine in Eclipse but as soon as I move my /war directory to the server (including the necessary mysql-connector-java-5.1.18-bin.jar file for the java-connector), the local SQL database on my server is not getting updated. Why is it not working? Is this some kind of mysql config issue?
I have set up a database on the server with the exact same name and table as the one on my local machine (where I was debugging with Eclipse). I do not get any errors from GWT (so the server access works fine) and my SQL log files also show no errors.
I have tried to restart mysql, checked that port 3306 for mysql is open and listening, disabled the firewall, and tried both localhost and 127.0.0.1 for the host.
I cannot figure out what the problem is, PLEASE someone help me! I'm going crazy here!
Here is my server side code which works fine in Eclipse but not on the server!
package com.mycompany.mywebapp.server;
#SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
public String[] greetServer(String[] input) {
//Data is entered into MySQL database on server side
Connection con = null;
Statement st = null;
String url = "jdbc:mysql://127.0.0.1:3306/testdb";
String user = "username";
String password = "pass";
try{
con = DriverManager.getConnection(url,user,password); //establishes connection to database
st = con.createStatement(); //object for sending SQL statements to database
for (int i=0;i<input.length;i++){
String DataToSend = input[i];
String part1 = DataToSend.substring(0,DataToSend.indexOf("["));
String part2 = DataToSend.substring(DataToSend.indexOf("["),DataToSend.indexOf("]")+1);
//store values into mysql database
String query = "INSERT INTO boundingboxes(name, box) VALUES('"+part1+"','"+part2+"')";
st.executeUpdate(query);
}
}catch (SQLException ex){
Logger lgr = Logger.getLogger(Version.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}finally{
//make sure to avoid null pointerexception
try{
if (st !=null){
st.close();
}
if (con != null){
con.close();
}
}catch (SQLException ex){
Logger lgr = Logger.getLogger(Version.class.getName());
lgr.log(Level.WARNING, ex.getMessage(), ex);
}
}
return input;
}
}
I found the solution to my problems:
To get rid of the NoClassDefFoundError, the external .jar files used by your app should be copied into the /WEB-INF/lib/ directly.
Apache requires an extra configuration step for jdbc-msql. Firstly, make sure that you have set the correct GRANT permissions set up for your SQL database.
Next, follow his solution which is taken from: http://dev.mysql.com/doc/refman/5.0/en/connector-j-usagenotes-j2ee.html#connector-j-usagenotes-tomcat
First, install the .jar file that comes with Connector/J in $CATALINA_HOME/common/lib so that it is available to all applications installed in the container.
Next, Configure the JNDI DataSource by adding a declaration resource to $CATALINA_HOME/conf/server.xml in the context that defines your web application:
<Context ....>
...
<Resource name="jdbc/MySQLDB"
auth="Container"
type="javax.sql.DataSource"/>
<!-- The name you used above, must match _exactly_ here!
The connection pool will be bound into JNDI with the name
"java:/comp/env/jdbc/MySQLDB"
-->
<ResourceParams name="jdbc/MySQLDB">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!-- Don't set this any higher than max_connections on your
MySQL server, usually this should be a 10 or a few 10's
of connections, not hundreds or thousands -->
<parameter>
<name>maxActive</name>
<value>10</value>
</parameter>
<!-- You don't want to many idle connections hanging around
if you can avoid it, only enough to soak up a spike in
the load -->
<parameter>
<name>maxIdle</name>
<value>5</value>
</parameter>
<!-- Don't use autoReconnect=true, it's going away eventually
and it's a crutch for older connection pools that couldn't
test connections. You need to decide whether your application
is supposed to deal with SQLExceptions (hint, it should), and
how much of a performance penalty you're willing to pay
to ensure 'freshness' of the connection -->
<parameter>
<name>validationQuery</name>
<value>SELECT 1</value> <-- See discussion below for update to this option -->
</parameter>
<!-- The most conservative approach is to test connections
before they're given to your application. For most applications
this is okay, the query used above is very small and takes
no real server resources to process, other than the time used
to traverse the network.
If you have a high-load application you'll need to rely on
something else. -->
<parameter>
<name>testOnBorrow</name>
<value>true</value>
</parameter>
<!-- Otherwise, or in addition to testOnBorrow, you can test
while connections are sitting idle -->
<parameter>
<name>testWhileIdle</name>
<value>true</value>
</parameter>
<!-- You have to set this value, otherwise even though
you've asked connections to be tested while idle,
the idle evicter thread will never run -->
<parameter>
<name>timeBetweenEvictionRunsMillis</name>
<value>10000</value>
</parameter>
<!-- Don't allow connections to hang out idle too long,
never longer than what wait_timeout is set to on the
server...A few minutes or even fraction of a minute
is sometimes okay here, it depends on your application
and how much spikey load it will see -->
<parameter>
<name>minEvictableIdleTimeMillis</name>
<value>60000</value>
</parameter>
<!-- Username and password used when connecting to MySQL -->
<parameter>
<name>username</name>
<value>someuser</value>
</parameter>
<parameter>
<name>password</name>
<value>somepass</value>
</parameter>
<!-- Class name for the Connector/J driver -->
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<!-- The JDBC connection url for connecting to MySQL, notice
that if you want to pass any other MySQL-specific parameters
you should pass them here in the URL, setting them using the
parameter tags above will have no effect, you will also
need to use & to separate parameter values as the
ampersand is a reserved character in XML -->
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost:3306/test</value>
</parameter>
I am using SQL Server Integration Services (SSIS) in SQL Server Business Intelligent Development Studio.
I need to do a task that is as follows. I have to read from a source database and put it into a destination flat file. But at the same time the source database should be configurable.
That means in the OLEDB Connection Manager, the connection string should change dynamically. This connection string should be taken from a configuration/XML/flat file.
I read that I can use variables and expressions to change the connection string dynamically. But how do I read the connection string value from a config/XML/flat file and set the variable?
This part I am unable to do. Is this the right way to achieve this? Can we add web.config files to an SSIS project?
First add a variable to your SSIS package (Package Scope) - I used FileName, OleRootFilePath, OleProperties, OleProvider. The type for each variable is "string". Then I create a Configuration file (Select each variable - value) - populate the values in the configuration file - Eg: for OleProperties - Microsoft.ACE.OLEDB.12.0; for OleProperties - Excel 8.0;HDR=, OleRootFilePath - Your Excel file path, FileName - FileName
In the Connection manager - I then set the Properties-> Expressions-> Connection string expression dynamically eg:
"Provider=" + #[User::OleProvider] + "Data Source=" + #[User::OleRootFilePath]
+ #[User::FileName] + ";Extended Properties=\"" + #[User::OleProperties] + "NO \""+";"
This way once you set the variables values and change it in your configuration file - the connection string will change dynamically - this helps especially in moving from development to production environments.
Some options:
You can use the Execute Package Utility to change your datasource, before running the package.
You can run your package using DTEXEC, and change your connection by passing in a /CONNECTION parameter. Probably save it as a batch so next time you don't need to type the whole thing and just change the datasource as required.
You can use the SSIS XML package configuration file. Here is a walk through.
You can save your configrations in a database table.
Here's some background on the mechanism you should use, called Package Configurations: Understanding Integration Services Package Configurations.
The article describes 5 types of configurations:
XML configuration file
Environment variable
Registry entry
Parent package variable
SQL Server
Here's a walkthrough of setting up a configuration on a Connection Manager: SQL Server Integration Services SSIS Package Configuration - I do realize this is using an environment variable for the connection string (not a great idea), but the basics are identical to using an XML file. The only step(s) you have to change in that walkthrough are the configuration type, and then a path.
Goto Package properties->Configurations->Enable Package Configurations->Add->xml configuration file->Specify dtsconfig file->click next->In OLEDB Properties tick the connection string->connection string value will be displayed->click next and finish package is hence configured.
You can add Environment variable also in this process
These answers are right, but old and works for Depoloyement Package Model.
What I Actually needed is to change the server name, database name of a connection manager and i found this very helpful:
https://www.youtube.com/watch?v=_yLAwTHH_GA
Better for people using SQL Server 2012-2014-2016 ... with Deployment Project Model