Would it be possible to programmaticly create a data source in jboss and still have a valid jndi entry for the entity manager to use?
Creating the data source is where I am lost, I hope I can use a MBean that runs on stat-up to handle this.
This would not be my preferred method, but the application I am working on has a global configuration file hosted on another server I am suppose to use for configuration.
update: In this instance I need to create a data source programticly or change the jdbc url of an exsiting datasource. I don't know the DB server url until runtime.
Rather than poking around in the guts of JBoss in order to do this, I suggest using a 3rd-party connection pool utility, such as Apache Commons DBCP. There are instructions on how to programmatically register a DBCP datasource on JNDI here.
The first two lines of the sample code should be unnecessary, just create the default InitialContext and then rebind the datasource reference into it as described.
Here's a post that describes how to create a jboss service archive (SAR) that you can put in your EAR that will deploy a data source when the EAR is deployed, and remove it when the EAR in undeployed.
Related
We had recently moved to building projects using Maven. Earlier, all the JARs were added in libs folder and added to classpath. While moving to the Maven build, I missed to add a dependency to the 'sqlite-jdbc'. This library is required to read data from a local .db3 file.
As the 'org.sqlite.JBDC' class was loaded by calling the code Class.forName("org.sqlite.JDBC"), there was no compilation error and I deployed the WAR file and servlet failed in the server. I was thinking of a way to find the issue at the compilation time itself to avoid any such mistakes in the future. Can I simply call the JDBC.PREFIX to load the JDBC, so that, If I forget to add the dependency to the pom.xml file, I can find the issue at the compile time, itself?
Is there was difference between Class.forName("org.sqlite.JDBC") vs JDBC.PREFIX to load JDBC class?
No need for Class.forName
There is no generally no need to call Class.forName.
Such calls were used in the early years. Modern Java was changed so that JDBC drivers are automatically loaded and registered with the JVM via the Java Service Provider Interface (SPI) facility.
If you are using books or tutorials advising Class.forName, you may want to obtain more up-to-date learning materials.
DataSource
Furthermore, in Servlet work you generally should not be explicitly accessing the JDBC driver.
Setting the database server address, username, and password would require hard-coding text. When the deployment sysadmins change the IP address, or rotate passwords, your code breaks. You would then have to modify your source code, re-compile, and re-deploy.
Instead, you should externalize such configuration details.
For SQLite, see Using DataSource to connect to SQLite with (Xerial) sqlite-jdbc driver.
JNDI
You can externalize database configuration by using the the DataSource interface. After obtaining a DataSource object at runtime, make database connections by calling its getConnection method. That DataSource object holds the database server address, username, password, and all other settings needed to make a connection to the database.
Obtain a DataSource object at runtime by using JNDI. Your Servlet container may act as the naming/directory server to provide the DataSource object, if your sysadmin so configures it. Or the DataSource can be obtained via JNDI from an external server such as an LDAP server.
Again, the beauty of using DataSource and JNDI is that you as the Servlet programmer need not be involved, or even informed, when the deployment details change.
JDBC driver location
For Servlet work, you generally do not bundle the JDBC driver with your app.
Instead, the JDBC driver goes into a folder managed by your Servlet container. Study the documentation for your particular Servlet container. For Apache Tomcat, see this Answer.
In development, your IDE may need access to the JDBC driver to compile. If so, in your Maven POM, mark the dependency with a <scope>provided</scope> element. This tag tells Maven to omit that dependency from the final build because the dependency will already be present (provided) at runtime.
If you insist on bundling your JDBC driver within the WAR file of your web app, then see the important Comment by Mark Rotteveel.
This topic has been addressed many times on Stack Overflow. Search to learn more.
I have a wildfly 10 (Java + Spring) project. I have a requirement to dynamically inject the datasource (mysql) config details to wildfly. But since wildfly depends on the standalone xml file at startup, and needs it before even the java beans are created, the only way I've found so far is to inject is by setting env vars (by running some other program/script to fetch the configs before wildfly starts). Is there any other better option?
Is it possible to do this through the same java application itself, ignoring the xml and set the right config? If yes, how?
DataSource object via JNDI
Externalize your JDBC connection details by using JNDI to access a naming/directory server to obtain an object implementing the DataSource interface.
With a DataSource object in hand, call getConnection to obtain a Connection.
See tutorial by Oracle, Connecting with DataSource Objects.
I'm writing a web application in Java and use Hibernate to map the database with my java objects. In Hibernate I connect to the database using C3PO pool. Now I need to schedule some tasks. Herefore I will use Quartz. Now the scheduled tasks will be stored in the database. It is possible to share the connection pool of C3PO with Quartz? So that the database settings are in one and the same file and that only one library is responsible to open a databaseconnection.
This is sort of a subjective thing, but suffice it to say, if you want to share the connection you have a number of options.
If you are using spring, define the c3p0 connection pool as a bean and inject it into both the Hibernate session factory and the Quartz scheduler beans.
If you are trying to stay "pure" and not using Spring, you can define your a JNDI based data-source at the container level.
There are some nuances with both approaches.
Unfortunately without indicating how "portable" you are trying to be and what you are currently using beyond just 'java', 'quartz-scheduler' and 'c3p0' as tags an answer will be vague at best.
EDIT
Thanks to the OP for adding additional information.
So with regard to that information, if you are using a Dynamic Web Project, you may be able to add a container specific deployment descriptor to WebContent directory.
For tomcat, META-INF/context.xml
For Jetty, WEB-INF/jetty-web.xml
With those, you can define a JNDI data source. Refer to the specific container for information on how to do that. Once done, Hibernate and Quartz can be configured to use a JNDI reference for the data source you have configured.
I used Tomcat's JDBC connection pool previously where it could be easily configured in Java.
Now I use Jetty 8.
How can I use JDBC connection pooling in Jetty? I looked here however I don't know where to put those XML snippets.
You can configure all JNDI resources in a jetty.xml file or in a WEB-INF/jetty-env.xml file, or a context XML file. For more information, see JNDI.
You will also need to add the pool implementation jar file to the classpath.
I've got a web application, hosted with tomcat, which uses hibernate to talk to a database.
I'm looking at how I can easy the pain of configuration as I migrate from dev, to test and to prod.
I've seen JNDI mentioned a lot and at first glance it seems like a good idea. You configure a jndi resource on each tomcat instance and the web context just uses it.
However after examining it further it seems that in order to have a JNDI I've got to have all my database objects + hibernate in the tomcat lib files in order for this to work. This sounds scary to me, what if I want to deploy another context that uses a different version of hibernate?
Also, am I not just swapping the pain of maintaining configuration for the pain of breakages caused by mismatches between the installed jndi resource classes and the ones in my context.
Ideally I think what I'm wanting is to just say in tomcat. There is a database called X, it is at this server and has this user/pass.
I'd appreciate your thoughts on the best way to handle the need for different config in different environments without having an extra step after each deploy to update the config files.
Cheers,
Peter
You have confused things a bit, I believe.
JNDI is just a name assigned to a datasource pool. This datasource uses a JDBC driver which in global Tomcat classpath, but that about the only shared resource in the whole setup.
Datasource has connection URL, username, password and options for connections defined, which may differ per server, but application doesn't care about it -- all it knows is the JNDI name, e.g. "jdbc/myDatasource".
All hibernate JARs, and well as any other JARs and whats not are to be packaged within the WAR. They are "visible" only within the WAR, and therefore you can have multiple applications using conflicting versions of libraries deployed to the same Tomcat.
No need to pollute lib/ directory of Tomcat. This is a bad practice, as you correctly observed.