Passing variables to a JRuby application via Tomcat config - java

What's the best way to configure variables in a JRuby application that's deployed as a WAR file? The operations group will need to configure database settings and other environment variables depending on where my app is deployed. Since it's a WAR file though they don't have direct access to the database.yml or any of the environment files.
I want to be able to variablize anything they need to configure and have them perhaps put something into the Tomcat app.config/web.config. Is this possible to do? How do you bring those values into JRuby?

So to get parameters from the Tomcat servlet context in JRuby is very simple I discovered:
$servlet_context
So for example if I had the following defined in the web.xml:
# from inside the web.xml context
<context-param>
<param-value>jdbc:h2:localhost/~/test_db</param-value>
<param-name>database.url</param-name>
</context-param>
You can access the value in JRuby as follows:
$servlet_context.getInitParameter("database.url")
This would return the string "jdbc:h2:localhost/~/test_db".

Related

How do configure grails to preserve your grails.app.context variable when generating a war?

With grails you change the rootContext of the application when running it using grails run-app by using the grails.app.context variable. However, when generating a war grails allows the servlet container to set the context by leaving the configuration out of web.xml. Is there any way to preserve the config in web.xml?
No, there is no way. As said earlier, grails.app.context is used for run-app where we know the embedded servlet container is either Tomcat or Jetty.
In case of a war, the application will not know which container will the war be deployed. It is upto the container to set the context root which vary from one to another.

Dynamic Change of files directory for jdbc.properties and log4j.properties

I'm working in a Java Web Project.
I need to change the folder of the files "jdbc.properties" and "log4j.properties" depending of the environment, because testing, demo and release have diferent values for those files.
I have this folders and subfolders:
c:\myProject\conf\dev
c:\myProject\conf\test
c:\myProject\conf\demo
I need to put diferent jdbc.properties and log4j.properties files in each of those folders
c:\myProject\conf\dev\log4j.properties
c:\myProject\conf\dev\jdbc.properties
c:\myProject\conf\test\log4j.properties
c:\myProject\conf\test\jdbc.properties
c:\myProject\conf\demo\log4j.properties
c:\myProject\conf\demo\jdbc.properties
The three project are in the same Server and in the same Apache (It is a Web Project)
First i made some changes to use a windows system variable to get the parent folder (c:\myProject). To do that, i made this on Spring appContext file:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>file:${PARENT_FOLDER}/conf/dev/jdbc.properties</value>
</property>
</bean>
"PARENT_FOLDER" is defined on Windows environment variables/system variable
Those changes works OK.
But, as you can see, I always loking for file on "/conf/dev"
I need to make dynamic the "dev" part of the path.
I Can't use Windows environment variables/system variable because the 3 environments are deployed on the same Server.
I'm trying to use a "property" (using ) on web.xml, but I don't know how to find the property in my Spring appContext file.
I definy the property like this:
<env-entry>
<env-entry-name>ENVIRONMENT</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Dev</env-entry-value>
</env-entry>
But I don't know how to access "ENVIRONMENT" property on Spring
I don't know what to do. I a little desperate
Can someone help me?
Thanks and sorry for my poor english
Have you considered using JNDI?
With JNDI you will define the db connection properties inside tomcat itself. This way your spring configuration is independent of the environment and you can deploy the same war on all environments. See also this.
If you need to run it locally that you can always use the 'new' spring environment profiles feature.
Other option (if JNDI is not an option and assuming you use maven) is the maven replacer plugin where you will generate the db.properties at build time.

Relative path to hsqldb files in a web app doesn't work?

I'm using hsqldb for my Spring-based java webapp. I put database files (mydb.lck, mydb.properties,..) in src\main\java\data folder so that they're published into WEB-INF\classes\data.
In datasource configuration, I specify this relative path to JVM working directory. As guided in hsqldb documents.
portal.jdbc.url=jdbc:hsqldb:file:/data/mydb (Is this seperator right for Windows?)
But Spring seem not find this path and insist on claiming
java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: CUSTOMER
org.hsqldb.jdbc.Util.sqlException(Unknown Source)
However, if I specify an absolute path, it works flawlessly
portal.jdbc.url=jdbc:hsqldb:file:d:\\TomcatServer\\apache-tomcat-7.0.10\\wtpwebapps\\myportal-app\\data\\mydb
Should I miss understanding JVM working directory on a web app?
Any help is appreciated.
It seems that Tomcat doesn't provide us a properties variable (like "webroot") to refer to my application context. So my solutions is to register such a properties in Servlet context listener.
My code:
public class WebAppPropertiesListener implements ServletContextListener{
#Override
public void contextInitialized(ServletContextEvent sce) {
String rootPath = sce.getServletContext().getRealPath("/");
System.setProperty("webroot", rootPath);
}
...
}
And add listener in web.xml before Spring context is triggered
<listener>
<listener-class>com.iportal.util.WebAppPropertiesListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Then I put the property in Hsqldb setting.
portal.jdbc.url=jdbc:hsqldb:file:${webroot}WEB-INF/classes/data/mydb
Hope this helpful for someone who may run into the same problem.
HSQLDB 2.2.8 and later allows a variable in the connection URL. The variable can be any system property, such as the web application directory path.
http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#dpc_variables_url
Refer Section "Variables In Connection URL"
http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html
Example
jdbc:hsqldb:file:${mydbpath};sql.enforce_types=true
Figured it out on Tomcat 8 thanks to fredt's answer.
url = "jdbc:hsqldb:file:" + mydbpath;
Where mydbpath is a variable with realtive path to the database specified.
This somehow works

How to set a parameter for a Java Web application

I have a web app in Java, which uses some external program (invokes a command line tool).
I want to make the path of the command line program configurable, so that I can change it without re-building my application.
Questions:
1) Which exactly parameter should I use (out of those available in web.xml), if it is set only once (at deployment) and thereafter never changes?
2) How can I access this parameter inside my Java code?
Thanks in advance
Dmitri
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
<context-param>
<param-name>command</param-name>
<param-value>SOME_COMMAND</param-value>
</context-param>
.
.
.
.
</web-app>
Java code
String commandToExecute = getServletContext().getInitParameter("command");
Alternatively
You can also put this thing in property/xml file in the classpath read it and put it to servlet context when context initializes.
You may use an env-entry:
<env-entry>
<description>command line</descriptor>
<env-entry-name>commandLine</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>some_command</env-entry-value>
</env-entry>
And get it from anywhere in your webapp code:
javax.naming.Context ctx = new javax.naming.InitialContext();
String command = (String) ctx.lookup("java:comp/env/commandLine");
I would go with a system property in this scenario. Just run your application server with a JVM flag like -Dyour.command.path=/path/to/your/command and then in the code, you just need to write:
String cmd = System.getProperty("your.command.path", "/some/default/fallback/path/cmd");
This way you won't rely on running in some Java EE / servlet container.
It's a two part solution.
First we can make a properties file that is accessible for the web application. This need not be your standard message properties, but a secondary file.
Second your deployment script and your build script can do some extra work to create context directories in the application server where it can copy the properties file from the build and make it available for the command line tools also.
Apache CLI is a very good alternative to do some programmatic access.

Different spring XML files for development environment vs. deployment when using maven

Summary
We have a central LDAP server that our deployed Java web app should connect to. Our JUnit tests depend on specific data in the LDAP repository, so they need to connect to an embedded ApacheDS LDAP server, primed with a sample data set. How do we make sure that the ApacheDS server doesn't start up when we deploy our webapp?
Details
We are using Spring security, and have the following line in ldap-context.xml to start up the embedded LDAP server:
<security:ldap-server root="dc=test,dc=com" port="33389" ldif="classpath:EmbeddedServerRoot.ldif" />
Currently, our web.xml references both this test context file and our top-level application-context.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:ldap-context.xml
classpath:application-context.xml
</param-value>
</context-param>
We need to make sure that ldap-context.xml is included when we run our JUnit tests, and when we run the webapp directly from eclipse (via WTP), but excluded when we package the war and deploy it to a server.
We're using maven as the build tool. We can fairly easily take care of this situation for our JUnit tests by making sure they include both spring context files in the context configuration:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:ldap-context.xml", "classpath:application-context.xml" })
public class TestStuff {
}
Then, our web.xml would only include application-context.xml, except for one thing - this doesn't work when running from WTP - we need the embedded server to start up in that case as well. Any suggestions?
If you're using Maven, why not use the Assembly plugin to manage your environment deployments. It seems like your spring file is not that complex, so you can have a common spring file which doesn't have the ldap-context.xml reference, and then a test-specific version which does have the ldap reference. When assembly is configured and run, the environment specific file will overwrite the common version, and then you can deploy your packaged app.
An other possibility is to use some properties in the pom and a filtered spring bean file defining aliases for the beans to switch between environments. But you need to habe both beans in the config, but you will use the one or the other.

Categories