I usually use Commons Configuration for manage my applications configs. I have used properties files configuration. Now I'm interested in using a JNDIConfiguration but I'm not able to understand how this works reading the documentation or googling it.
Contextualizing, I'm working in webapps running in an JBoss AS.
Where will be the properties stored? In a file? some tables in a database?
I will be grateful for any guidance at this level even if it comes in shape of links where I can read some valuable information about it.
As a final note my goal is to free me of linking a file with a hardcoded path for my properties, but also don't force me to have my config in database tables. If you have any suggestions on how to do that in some other way be free to share.
JNDIConfiguration looks up the configuration data on a JNDI server (in your case, the JBoss JNDI server). However, you still need a way of getting that data into the JNDI server in the first place, and Commons-Configuration won't help you with that.
It sounds to me that JNDI isn't what you want, it's just pushing the problem around a bit. JBoss still needs to store the configuration data somewhere, so you'll still have the same basic problem.
If you don't want hard-coded file paths, and you don't want a database, then I suggest you pass in the location of the properties file via a system property, e.g.
java -Dmy.config.path=/my/config.properties com.MyClass
Then pass that location to Commons Configuration and let it load your config that way. No hardcoded-paths, no database.
I don't know much about Commons Configuration and JNDIConfiguration, but if what you want is a set of key/value pairs, the standard way of doing this as per the Java EE specs, is to use env-entry in the web.xml or ejb.xml.
<env-entry>
<env-entry-name>maxExemptions</env-entry-name>
<env-entry-value>10</env-entry-value>
<env-entry-type>java.lang.Integer</env-entry-type>
</env-entry>
(example taken from JBoss web conf. reference.)
These values are bound in the JNDI so they can be looked up or injected.
Where will be the properties stored? In a file? some tables in a database?
As #ewernli mentioned, the Java EE way to add entries in the JNDI tree is to use env-entry in your deployment descriptor(s).
Now, if you don't want to repeat the same env-entry in several deployment descriptors, then there is a service for specifying global JNDI bindings: JNDIBindingServiceMgr.
Below, the provided jboss-service.xml example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE server PUBLIC "-//JBoss//DTD MBean Service 4.0//EN"
"http://www.jboss.org/j2ee/dtd/jboss-service_4_0.dtd">
<server>
<mbean code="org.jboss.naming.JNDIBindingServiceMgr"
name="jboss.tests:service=JNDIBindingServiceMgr">
<attribute name="BindingsConfig" serialDataType="jbxb">
<jndi:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd"
>
<jndi:binding name="urls/jboss-home">
<jndi:value type="java.net.URL">http://www.jboss.org</jndi:value>
</jndi:binding>
<jndi:binding name="hosts/localhost">
<jndi:value editor="org.jboss.util.propertyeditor.InetAddressEditor">
127.0.0.1
</jndi:value>
</jndi:binding>
<jndi:binding name="maps/testProps">
<java:properties xmlns:java="urn:jboss:java-properties"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="urn:jboss:java-properties resource:java-properties_1_0.xsd">
<java:property>
<java:key>key1</java:key>
<java:value>value1</java:value>
</java:property>
<java:property>
<java:key>key2</java:key>
<java:value>value2</java:value>
</java:property>
</java:properties>
</jndi:binding>
</jndi:bindings>
</attribute>
<depends>jboss:service=Naming</depends>
</mbean>
</server>
If this is not what you are looking for, then I don't understand what you're looking for :) In that case, you should maybe clarify it.
Related
I've just started working with Spring/java web. I'm wondering how to accomplish following scenario:
Let's say that I'm creating an application which supports file upload, uses a database connection and maybe a web service. This is an off-the-shelf system, so all the settings are customer specific and should be configured by customer's IT people on the deployment time.
More general in the web.xml file I would like to point the application working directory containing uploaded files, license key file, configuration files, other customer specific resources and maybe even fragments of spring context.
<context-param>
<param-name>workdir</param-name>
<param-value>/var/r2/</param-value>
</context-param>
In my application I would like use the workdir value in order to include configuration files ...
<import resource="wordir_param_value/settings.properties" />
context config fragments
<import resource="wordir_param_value/security.xml"/>
And how may I later use these values in the java code? What is "the best" approach in case like this anyway (off-the-shelf application config)?
Best Regards,
Alek
You can use Spring's property support for that. This allowed two different approaches:
Having a property file outside the application (at a fixed location), the admin can edit it, and the application loads it
In a Tomcat you can write properties in the application specific context.XML file
In the code use #value annotation to inject the properties in a variable.
In the spring XML file you use it with ${name}
Of course you need to configure the proprtyPlaceholderConfigurer
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
How do I add custom queues to JBoss 5.1.0?
I found a way to do it via the Admin Console however for some reason it keeps failing, also I need to be able to quickly and easily move my queues from one JBoss Server to another.
So basically I was wondering if there is a way to create custom queues in an xml file and add that file to the deploy folder much like how you can do with a custom datasource file (mydatasource-ds.xml).
Thank you.
Create a file ending with destinations-service.xml under your instance's deploy directory (or deploy/messaging if you like), e.g. my-jms-destinations-service.xml. It should look something like:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Messaging Destinations deployment descriptor.
-->
<server>
<mbean code="org.jboss.jms.server.destination.QueueService"
name="jboss.messaging.destination:service=Queue,name=MyQueue"
xmbean-dd="xmdesc/Queue-xmbean.xml">
<attribute name="JNDIName">MyQueue</attribute>
<depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
<depends>jboss.messaging:service=PostOffice</depends>
</mbean>
</server>
Set the mbean name and JNDI name as required. Add more mbean definitions for additional queues, or split them across multiple *destinstations-service.xml files for easily deploying / undeploying queues independently of each other.
this may come a little late, but I also had a few errors when creating queues through the Admin console.
The error was due to a missing folder named queue inside the deploy folder. After creating the queue folder, I was able to create the queues using the admin console.
I know that for JBoss you need a [name]-ds.xml file in the /deploy subdirectory of the appropriate instance.
i dont have any experience with other Java EE containers, but im trying to stick to standards as much as possible.
is there a standard way to define a JDBC datasource and deploy it ? if possible i'd like to include my datasource inside the *.ear file (for instance, an embedded in-memory HSQLDB datasource for demo purposes) ?
if there is no standard way, will other containers at least accept the jboss way ? (/deploy/*-ds.xml)
Is there a standard way to define a JDBC datasource and deploy it?
Yes, there is. It's done via the <data-source> element, which you can put in web.xml, ejb-jar.xml and application.xml. If you don't like XML, you can also use an annotation for this instead: #DataSourceDefinition
Example of a web.xml entry
<data-source>
<name>java:app/myDS</name>
<class-name>org.postgresql.xa.PGXADataSource</class-name>
<server-name>pg.myserver.com</server-name>
<database-name>my_db</database-name>
<user>foo</user>
<password>bla</password>
<transactional>true</transactional>
<isolation-level>TRANSACTION_READ_COMMITTED</isolation-level>
<initial-pool-size>2</initial-pool-size>
<max-pool-size>10</max-pool-size>
<min-pool-size>5</min-pool-size>
<max-statements>0</max-statements>
</data-source>
Further reading:
Introducing the DataSourceDefinition Annotation
The state of #DataSourceDefinition in Java EE
Example application use standard data source
p.s. I'm surprised all other answers say this doesn't exist, while it clearly does, even at the time this question was originally asked.
Is there a standard way to define a JDBC datasource and deploy it ?
No, this is container specific. As Application Component Provider, you're supposed to document the resources you need and the Application deployer and Administrator will configure them.
If there is no standard way, will other containers at least accept the JBoss way?
No, because this is the JBoss way and thus JBoss specific.
With Tomcat, you would have to use the context.xml file.
With Jetty, jetty-env.xml.
With WebSphere, you can create a so called WebSphere Enhanced EAR.
With WebLogic, you can package a JDBC Module in your application.
With GlassFish, you can use the command asadmin add-resources my.xml to add a datasource described in a XML file (example here).
Etc, etc.
Note that there are some projects trying to achieve this goal in a universal way like jndi-resources or Cargo. There are also more complex solution like ControlTier or Chef.
Now, in your case (as I understood you want to use an embedded database that will be bundled with your application), I don't think you should configure a datasource at the application server level. You should just package the jar of your database in your application with a standalone connection pool like c3p0 or DBCP.
Sun's Java EE philosophy defines several roles in the design, development and deployment of an enterprise application. Java EE design accommodates and reflects these separations of concerns.
In particular Sun wants to separate the developer from the administrator of an application, which is a good idea. The developer writes enterprise components in a container-agnostic way. In web.xml, for example, you do declare your DataSources in a standard way:
<resource-ref>
<res-ref-name>jdbc/myDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
This says "this database thing the application needs, make it available to me, whatever database is and whatever container you're running it in, via standard JNDI at 'jdbc/myDB' ". This is as much as the developer can do -- the rest is necessarily container specific and therefore not standardized.
And then how "myDB" is actually configured is up to a different role, the administrator of the container.
So I'm repeating the correct answer above: no. But the reason is, otherwise, you'd be coding your app to a specific type of database on a specific host and port, and the point is that you shouldn't be able to do that, so there's no standard support for that on purpose.
I've context.xml in my web/meta-inf/ folder containing database connection (pool) details. Now i want the database details for my application to be provided by end user in some properties file and context.xml reading the db connection info from the properties file instead of hard coing them in the file directly.
is it possible for tomcat to replace the placeholders from some properties file?
i read about context-manager but not sure where to place that.
Please provide your inputs.
Thanks
Abhishek
You can do it in a better way.
In our case we had different databases for different profiles, like dev, UAT, pre-prod, support etc.
So what I did was, I put my context.xml in its default location <TOMCAT_HOME>/conf.
Had the following in the resource config of context.xml:
<Resource name="jdbc/someDS"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="${appName.db.url}"
username="${appName.db.user}"
password="${appName.db.password}"
maxActive="30"
maxIdle="10"
defaultAutoCommit="true"
maxWait="-1"/>
I created three tomcat servers - server-dev, server-uat, server-support
and passed the corresponding values for each database in the vm arguments of tomcat in eclipse/intellij's tomcat server config (like shown below):
-DappName.db.url=jdbc:oracle:thin:#<DB_SERVER>:1521:<SID> -DappName.db.user=DB_USER -appName.db.password=DB_PASSWORD
The advantage is, the developers then don't need to change the database every-time, they just need to start a particular server. This was very handy and saved a lot of time during our development.
Adding the JNDI resources to Context.xml isn't enough. You will need to define their use in WEB-INF/web.xml also. Check this for a step by step.
As I understand it, your goal is to have application configuration outside of your .war to allow a system administrator to configure the system.
One way to achieve that is to not place the context.xml in your .war file but to distribute that file alongside with your .war.
This file then has to be placed placed in CATALINA_HOME/conf/Catalina/HOSTNAME/APPLICATIONPATH.xml (e.g. CATALINA_HOME/conf/Catalina/localhost/myapp.xml).
This way, the database connection information can be edited directly in the external context configuration file without changing the .war file, you won't need placeholders in that scenario.
This is not the most comfortable way for the user as he/she has to edit an xml file but it should be feasible for most system administrators...
You can find more information on tomcat context configuration at tomcat.apache.org/tomcat-5.5-doc/config/context.html
I'm not sure it's possible to load the details from a properties file but you can have the details in the central server.xml file rather than context.xml. Once you've achieved that, you could probably externalize the connection details using a standard XML entity reference.
Instead of putting your database connection details in the context.xml, put them in the server.xml under a section, and then add a ResourceLink element to the context.xml that creates a link between the global data source and your context.
Unfortunately the documentation is fairly weak for what you're trying to achieve.
Follow the instructions on the "Resource Definitions" section of this page (about half way down), and pay particular attention to the (tiny) ResourceLink section below it:
http://tomcat.apache.org/tomcat-5.5-doc/config/globalresources.html
If I don't have database connection information at build time, I'll just configure a resource reference and tell the admin what name they need to give the connection pool. They can configure everything in the Tomcat admin console and I never have to know about it. This also makes it easier to build a single WAR file and use it in multiple environments since the database configuration details aren't part of the WAR.
See also:
Apache Tomcat 6.0 JNDI Resources
If you do know the details at build time and want to bake them into the WAR, try Ant filters.