This is a follow-up to a question I posted a while back: "Can I use a single WAR in multiple environments?". I was able to create a single-war solution in Tomcat, but now we are migrating our app to JBoss 4.2 and I can't figure out how to set up global environment variables.
In Tomcat 6 this was pretty straightforward: I simply put the following snippet in tomcat/conf/Catalina/myappname.xml:
<Context ...>
<Environment name="TARGET_ENV" value="DEV" type="java.lang.String" override="false"/>
</Context>
Then in my app I was able to resolve the environment name with the following:
Context context = (Context) InitialContext().lookup("java:comp/env");
String targetEnvironment = (String) context.lookup("TARGET_ENV");
The problem is that I can't find out where/how to place global variables in JBoss. I've tried putting the <Environment> tag in the following files to no avail:
server/all/deploy/jboss-web.deployer/context.xml
server/default/deploy/jboss-web.deployer/context.xml
I know that I can put environment variables in my app's web.xml but that defeats the purpose of having a unified war - I'd still need custom .war's for dev, qa and prod.
I'm a JBoss newbie so if there's any additional information that would help just let me know and I'll append to this question.
I use somehing similar to PropertiesService for database url, and other environment related things.
Therefore I'm relieved from the burden to provide different environment related atrifacts.
Related
I have a webapp that is a RestEASY JAX-RS application and that uses the latest servlet specifications, such as Java EE annotations so that I don't need to create a web.xml file.
The webapp is bundled as foobar.war and dumped into the webapps directory in Tomcat. In fact the same foobar.war is deployed twice in the same Tomcat instance, once as foobar.war and the other as foobar#demo.war (which maps it to foobar/demo as you know).
I configure each mounted webapp by placing conf/Catalina/localhost/foobar.xml and conf/Catalina/localhost/foobar#demo.xml files, that look like this:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="foo" type="java.lang.String" value="bar"/>
</Context>
In my JAX-RS application I pull in the value of foo from JNDI using java:comp/env/foo.
So now I added a Java-based Spring configuration named FooBarConfiguration. I load it in my JAX-RS application using new AnnotationConfigApplicationContext(FooBarConfiguration.class). That all works fine.
So now I've added two profiles to FooBarConfiguration, one named foo and one named bar. But now... how do I tell the webapp which Spring profile to use? (Remember that I have no web.xml file.) Obviously I have to set spring.profiles.active somewhere. But where?
Because the documentation spoke of "environment" and "JNDI", I crossed my fingers and added an environment variable to conf/Catalina/localhost/foobar.xml:
<Environment name="spring.profiles.active" type="java.lang.String" value="foo"/>
No luck.
I can't set a system property, because that will apply to all the webapps, and the idea here is that each foobar.war instance (foobar.war and foobar#demo.war) could each have a different profile specified.
I suppose I could manually pull it out of the Tomcat environment myself, using java:comp/env/spring.profiles.active, but then where do I set the value? (I thought maybe AnnotationConfigApplicationContext would have a constructor where I could set the profile, or at least have a profile setting, but that also seems to be missing.)
(Plus if I'm manually pulling out the setting from JNDI and setting it myself, I might as well switch to the more lightweight Guice and manually load the modules I want. I'm only using the humongous, clunky Spring because it promised to allow easy selection of profiles.)
How can I indicate, external to my WAR file, on a per-webapp basis, which Spring profile I'm using?
You can set active profiles in many ways. Since you were searching for it via AnnotationConfigApplicationContext constructor, the one described here in spring docs might suit you.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.refresh();
The solution is to use AnnotationConfigWebApplicationContext instead of StandardServletEnvironment.
The trick is to get Spring to use a StandardServletEnvironment, which looks in several places including JNDI java:comp/env/... for spring.profiles.active. See http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-property-source-abstraction .
My problem is that AnnotationConfigApplicationContext uses a StandardEnvironment, which only looks in a few places for the profile designation. Switching to a AnnotationConfigWebApplicationContext made Spring use a StandardServletEnvironment:
final AnnotationConfigWebApplicationContext webContext =
new AnnotationConfigWebApplicationContext();
webContext.register(FooBarConfiguration.class);
webContext.refresh();
Now my webapp environment configuration in conf/Catalina/localhost/foobar.xml works:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="spring.profiles.active" type="java.lang.String" value="foo"/>
</Context>
I try to secure my Java Servlet application with keycloak. All works fine but I don't like the fact that my 'keycloak.json' file is inside my release located. The reason is, if the keycloak definitions are inside my war, so I need for different installations different build processes or the same client credentials on different installations.
My idea was now to place the 'keycloak.json' outside my WEB-INF. Is this possible? Other ideas to solve this problem are also welcome.
if you check the KeycloakOIDCFilter you see there are three additional parameter.
keycloak.config.resolver
keycloak.config.file
keycloak.config.path
We are using file parameter and works like charme.
The Servlet-Filter mentioned above is not necessary.
It is enough to set a context-parameter, like #OkieOth said in his comment.
E.g. set a Parameter like this
<Parameter name="keycloak.config.file" value="MY-PATH/keycloak.json" override="false"/>
within your context (beside the for keycloak configured Valve) or a "context-param" in your web application deployment descriptor (/WEB-INF/web.xml):
<context-param>
<param-name>keycloak.config.file</param-name>
<param-value>MY-PATH/keycloak.json</param-value>
</context-param>
For more Detail about context-params, see The Context Container in section "Context Parameters".
I'd like to be able to implement a configuration-less deployment for my java application (tomcat7, spring-mvc). For example, right now we are considering creating one context.xml file for each environment (prod, stage, dev) we deploy to:
context_prod.xml
context_stage.xml
context_dev.xml
context.xml (for localhost)
On each of our servers we would have a symlink context.xml which would point to the appropriate context file (e.g. context_prod.xml). So when we deploy, we don't have to worry about changing database references, keys, etc.
I feel like there's probably a better way to do this; perhaps one that is built into spring?
Spring has recently added the functionality to handle environment configuration:
http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/
This still seems a little bit complicated for me and I have done exactly what you are asking in my own Spring MVC applications for our logging. In my DispatcherServlet configuation I have this line:
<context:property-placeholder location="classpath*:/system.properties"/>
<util:properties id="mySystemProperties" location="classpath:/logging/log4j-${system.runMode}.properties" />
system.runMode is just an env variable that we created and is set in CATALINA.SH at startup like this: Setting environment variable TESSDATA_PREFIX in Tomcat
I then use Spring EL to reference any values I want and it works per environment. As you can see I did this for our logging and have a different logging configuration file per environment.
You could use Spring #Profile introduced in Spring 3.1. In your case you could use profiles like dev, stage, prod etc.
This profile value could be initialized run time. So when your application started, Spring could fetch appropriate profile based on configuration.
You could setup profile from environment variable, via deployment descriptor (web.xml) etc. This Spring source tutorial could be interesting for you.
I personally using Maven build to replace the profile value during build time in the web.xml. In the build time I passed profile value as build argument.
I would like to disable page "People" in Hudson. I don't want users to see other users. Is it possible to do?
I don't know if you can do it directly with Hudson, but you certainly be able to do it if you run Hudson within a Tomcat instance (I run mine in a Tomcat 7 without any problem).
You would define a JSP security-constraint, a bit like those ones (note: adapted for LDAP because I defer all user authentication to the webapp container of Hudson: in my case, Tomcat)
The OP asks:
You're suggesting to make changes to hudson/WEB-INF/web.xml? Could you please explicitly mention the file I have to change?
#Vincenzo: I don't! I never touch one bit of the hudson.jar. I only use it within a Tomcat instance, meaning:
I declare in <tomcat>/conf/Catalina/localhost a context for each Hudson I want to manage:
hudson-xxx -> /home/me/context/hudson-xxx.xml
(it is a link because I want to upgrade Tomcat easily, so I externalize the context definition outside of Tomcat). I define my Realm for ACL purposes:
<?xml version='1.0' encoding='utf-8'?>
<Context docBase="/home/me/hudson/hudson.war" path="/hudson-xxx">
<Realm className="org.apache.catalina.real.CombinedRealm" >
<Realm className="org.apache.catalina.real.JNDIRealm" debug="99"
connectionURL="ldap://xxxxx:389"
alternateURL="ldap://xxxxx:389"
connexionName="yyyy"
connectionPassword="zzzz"
userPattern="CN={0},OU=...,DC=..."
userRoleName="memberOf"
useSubtree="false"
roleBase="OU=...,DC=..."
roleName="cn"
roleSearch="(member={0})"
roleSubtree="false"
/>
</Realm>
<Environment name="HUDSON_XXX" value="/home/me/hudson/hudson-xxx-home" type="java.lang.String" override="false" />
</Context>
(With that context, a hudson.war stored outside of Tomcat is automatically deployed with the </tomcat>/webapps directory, and access from http://tomcat-server/hudson-xxx, with an LDAP-based authentication)
I suggests modifying the </tomcat>/conf/web.xml to add security-constraint which would prevent anybody to access the user page while letting only certain tomcat users (as defined in /conf/tomcat-users.xml.
(I haven't tested it yet)
I am trying to set a system property in tomcat config file so it can be read by System.getProperty() code. This is probably a simple task but I am not able to figure this out. Here is want I tried with no success.
Modified context.xml in tomcat settings.
<Context>
....
<Parameter name="run.mode" value="test"/>
<Environment name="run.mode" value="test" type="java.lang.String"/>
</Context>
I don't want to modify container settings, just the server settings.
PS. I am fairly new to to the container and JVM webapp world. Still making sence of things. Right now I am working with Lift.
Use the JAVA_OPTS environment variable when launching Tomcat, like this:
JAVA_OPTS='-Drun.mode=test' start.sh