I have one query regarding datasource configuration.
I had configured one data source in server. Where my JNDI name is "MyDS".
To acquire the data-source in JBoss environment i had used like "java:/MyDS" in persistence, spring even in Birt reports.
But when i am running same thing in Tomcat environment, then it is showing error that unable to get the data-source.
I had googled about tomcat datasource communication, where i had seen like "jdbc/MyDS"
So, my query is what is the difference between above two types of configurations? (java:/MyDS and jdbc/MyDS) and how can i use the common configuration for both the servers (tomcat6 and jboss 5.1.0.GA).
Please help me.
Related
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'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.
Preface:
Most of J2EE applications are using container managed datasources through JNDI. This is fine as it gives one place for configuring these connections.
The problem arises when we want to use ORM framework (like hibernate) or something that have to know the default schema (mostly for Oracle, may be others too), which can be different from the username that is used to connect to the DB.
I want to put the default schema name somewhere close to the datasource definition. One of the options would be to put it in JNDI. I will then manually read of from there before construction the EntityManager (well actually using Spring).
As I found out there is a simple way to specify custom resource (in this situation it will be String with default schema name) in Apache Tomcat like this (correct me if I'm wrong):
<Environment name="schemaNames/EmployeeDB"
type="java.lang.String"
value="empl"
description="Schema name of Employees Database for HR Applications"/>
Anyway, considering this can be done in Apache Tomcat, how should I configure the same custom JNDI resource (of String type) within other application servers:
JBoss 4/5
WebSphere 6/7
WebLogic 9/10
If you know about other servers that would be great too.
Also, as an alternative I don't want to put the schema name in system properties or environment variables.
Thank you very much !
Update:
Found some way of achieving it on JBoss. I didn't test it tho.
http://forums.java.net/jive/thread.jspa?messageID=316228
Found information for WebLogic, but they talk about doing it programmaticly and not with configuration:
http://weblogic-wonders.com/weblogic/2010/06/12/binding-objects-in-weblogic-servers-jndi-tree/
http://forums.oracle.com/forums/thread.jspa?messageID=4397353
For WebSphere you can actually set the default schema in your defined DataSource. It is a custom property called currentSchema. (ie, in V7 it is Resources > JDBC > Data sources > your data source name > Custom properties > currentSchema.
Otherwise you can use a Name Space Binding and define it there: (ie, in V7 it is Environment > Naming > Name Space Bindings. You can use JNDI to look this up if you don't want to programmatically set it in WebSphere.
Can't speak to JBoss and WebLogic as I haven't worked with them.
If you are using Hibernate, this is the property to add in persistence unit :
<property name="hibernate.default_schema" value="myschema" />
That is the prefix that JPA will insert for table names.
If you need something 'closer' to the AS Datasources definitions, you may inject some DB-specific SQL at DB connection time; for instance Oracle,
ALTER SESSION SET CURRENT_SCHEMA =
On JBoss, you may add this in the datasource definition :
<new-connection-sql>
ALTER SESSION SET CURRENT_SCHEMA=myschema
</new-connection-sql>
Also editable in JBoss 7 Admin.
On Weblogic, you may inject this in the Connection Pools.
On Websphere, this should be similar.
On JBoss, you can use a special MBean(org.jboss.naming.JNDIBindingServiceMgr) and a service.xml to configure JNDI-entries, and then map these entries into your webapps. There is a lengthy explication for this rather non-trivial process here:
http://usna86-techbits.blogspot.com/2011/01/jboss-jndi-and-javacompenv.html
I'm still looking for a a way to place an entire properties-file/resourcebundle into jndi, as this manual mapping gets very tedious when you have a lot of properties that you want to put into jndi and make available for your webapps.
This same problem has been bothering be for quite a while for WebLogic, in particular 10.3.5 (11g).
I spent most of a day looking around and all I found was this: http://code.google.com/p/weblogic-jndi-startup/. It works just fine. It is a little restrictive: it requires the object you want to add to JNDI to have a constructor with a single String parameter.
For what I needed, weblogic-jndi-startup didn't work, so I built on Roger's code and came up with this: https://bitbucket.org/phillip_green_idmworks/weblogic-jndi-custom-resource-configuration/. I have a write up for it at http://coder-in-training.blogspot.com/2012/03/weblogic-jndi-custom-resource.html
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.
When I try the following lookup in my code:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
return (DataSource) envCtx.lookup("jdbc/mydb");
I get the following exception:
java.sql.SQLException: QueryResults: Unable to initialize naming context:
Name java:comp is not bound in this Context at
com.onsitemanager.database.ThreadLocalConnection.getConnection
(ThreadLocalConnection.java:130) at
...
I installed embedded JBoss following the JBoss wiki instructions. And I configured Tomcat using the "Scanning every WAR by default" deployment as specified in the configuration wiki page.
Quoting the config page:
JNDI
Embedded JBoss components like connection pooling, EJB, JPA, and transactions make
extensive use of JNDI to publish services. Embedded JBoss overrides Tomcat's JNDI
implementation by layering itself on top of Tomcat's JNDI instantiation. There are a few > reasons for this:
To avoid having to declare each and every one of these services within server.xml
To allow seemeless integration of the java:comp namespace between web apps and
EJBs.
Tomcat's JNDI implementation has a few critical bugs in it that hamper some JBoss
components ability to work
We want to provide the option for you of remoting EJBs and other services that can > be remotely looked up
Anyone have any thoughts on how I can configure the JBoss naming service which according to the above quote is overriding Tomcat's JNDI implementation so that I can do a lookup on java:comp/env?
FYI - My environment Tomcat 5.5.9, Seam 2.0.2sp, Embedded JBoss (Beta 3),
Note: I do have a -ds.xml file for my database connection properly setup and accessible on the class path per the instructions.
Also note: I have posted this question in embedded Jboss forum and seam user forum.
Thanks for the response toolkit.... yes, I can access my datasource by going directly to java:jdbc/mydb, but I'm using an existing code base that connects via the ENC. Here's some interesting info that I've found out ....
The above code works with JBoss 4.2.2.GA and here's the JNDI ctx parameters being used:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces:
org.jboss.naming:org.jnp.interfaces
The above code works with Tomcat 5.5.x and here's the JNDI ctx parameters being used:
java.naming.factory.initial=org.apache.naming.java.javaURLContextFactory
java.naming.factory.url.pkgs=org.apache.naming
The above code fails with Embedded JBoss (Beta 3) in Tomcat 5.5.x with the above error message.
java.naming.factory.initial=org.apache.naming.java.javaURLContextFactory
java.naming.factory.url.pkgs=org.apache.namingThe above code fails with the above error using JBoss Embedded in tomcat 5.5.x
Anyone have any thoughts I what I need to do with configuring embedded JBoss JNDI configuration?
java:comp/env is known as the Enterprise Naming Context (ENC) and is not globally visible. See here for more information. You will need to locate the global JNDI name which your datasource is regsitered at.
The easiest way to do this is to navigate to JBoss' web-based JMX console and look for a 'JNDIView' (not exactly sure of the name - currently at home) mbean. This mbean should have a list method which you can invoke, which will display the context path for all of the JNDI-bound objects.
I had some similar issue with Jboss Embedded and i finally fix playing in the file:
test-Datasource-ds.xml
adding
<mbean code="org.jboss.naming.NamingAlias" name="jboss.jmx:alias=testDatasource">
<attribute name="FromName">jdbc/Example DataSource</attribute>
<attribute name="ToName">java:/testDatasource</attribute>
</mbean>
The problem was jboss add the prefix java:/ for all data source declared. So finally i had a datasource named testDatasource, overrided with that directive to jdbc/Example DataSource
Hope it works