How to set a parameter for a Java Web application - java

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.

Related

Tomcat 8, publish 2 .war under same root directory

I have a Tomcat 8 instance which is used to publish multiple web applications.
As today, I have a Spring architecture which produces 2 .war:
Front-end
Back-end
And the result is the following:
http://localhost:8080/my-front-end
http://localhost:8080/my-back-end
What I would like to achieve is to have a common root path for both these wars. Is this something I can do in Tomcat? In JBOSS or IIS I can use the concept of "Virtual Directory" to achieve that.
My intended result is the following:
http://localhost:8080/my-app/my-front-end (my-front-end.war)
http://localhost:8080/my-app/my-back-end (my-back-end.war)
The Tomcat documentation says to use # in the name.
Context Name Base File Name Example File Names
/foo foo foo.xml, foo.war, foo
/foo/bar foo#bar foo#bar.xml, foo#bar.war, foo#bar
So use these names for your war files:
my-app#my-front-end.war
my-app#my-back-end.war
Set the context paths: /my-app/my-front-end and /my-app/my-back-end respectively.
For example, if you are using Spring Boot, then put:
server.contextPath=/my-app/my-front-end
and
server.contextPath=/my-app/my-back-end
in application.properties file.
If you cannot modify the application's source code, here you can find out how to configure Tomcat to get the same result.

Weblogic 12C - Is there a way to edit the variables of a deployment plan from the console?

We are new to Weblogic (12c). We try to choose how we're going to pass some configurations to the application depending on the environment it is running on (dev / staging /prod).
I'm currently trying to use a deployment plan. In WEB-INF/web.xml, I have :
<context-param>
<param-name>test</param-name>
<param-value>11111</param-value>
</context-param>
And I use a plan.xml for my application in Weblogic.
Some parts :
<variable-definition>
<variable>
<name>test</name>
<value xsi:nil="false">22222</value>
<description>some description</description>
</variable>
</variable-definition>
and
<module-descriptor external="false">
<root-element>web-app</root-element>
<uri>WEB-INF/web.xml</uri>
<variable-assignment>
<name>test</name>
<xpath>/web-app/context-param/[param-name="test"]/param-value</xpath>
<origin>planbased</origin>
<operation>replace</operation>
</variable-assignment>
</module-descriptor>
This works!
But I heard it could be possible to change the value of the variable from the administration console, is that true?
When I browse my application in the console (in the Deployment Plan tab or in the Configuration tab), I do not see any field which I could use to change the test variable... Am I missing something or must the values of overriding variables be set in the plan.xml file itself?
I do not think you can change the variable directly, I believe this is because it's a fundamental change to the deploy that requires a "hot update" BUT you can easily "redeploy/update" with a new plan. This is how you would do it in a production environment:
From the Weblogic admin console, click Deployments, click the checkbox next to your ear/war
Click Update
The next screen will ask you for the source path and the deployment plan path, you can change just the deployment plan path to set your new value(s)
You can also call java weblogic.Deployer with the update option if you want to do it from the command line.
It is also possible to do the same via WLST scripting - see these Oracle Docs

Tomcat 6 not recognizing <url-mapping>

I have what I think is the simplest possible
hello world example (see below). But when asking for
"http://localhost:8080/hello" thru firefox,
it gives me the
"The requested resource (/hello/) is not available"
error.
Environment: newly installed tomcat 6.0.32 on Windows 7.
Other information:
1. None of the "similar questions" provides any clues.
From experimentation, it appears that tomcat is not
doing the mapping from localhost:8080/hello to my servlet.
I set "<load-on-startup>"
which showed me that the servlet's init entry was being
called, but doGet() is never called.
The log files show no errors.
I have tried both starting tomcat with the hello
directory already in webapps, with hello.war in
webapps, and deploying using the manager application.
All act the same way.
Some possibilities I have considered:
According to the documentation, I should
not need to use a context.xml file, and my experiments
with a context.xml produced the same resource not found
error.
localhost:8080/hello should instead be
localhost:8080/.../hello, but if so, then what is
the ... supposed to be?
Trailing / (e.g. /hello versus /hello/). I changed
the url-pattern to "/hello/*", but it fails the same
way.
I assume the problem is something simple, but I cannot
see it.
[Added 8/8/2011]
The answers about using context.xml were correct; thanks.
In looking around, it appears that an alternate way
to achieve the same effect is to put this
into my web.xml file.
<context-param>
<param-name>ContextPath</param-name>
<param-value>/dts</param-value>
</context-param>
web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:/java.sun.com/dtd/web-app_2_3.dtd">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>test.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
HelloServlet.java:
package test;
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
public class HelloServlet extends HttpServlet {
public void init()
{
System.out.println("\nHelloServlet.init");
}
public void doGet (HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException
{
System.out.println("\nHelloServlet.doGet");
PrintWriter out = res.getWriter();
out.println("Hello, world!");
out.close();
}
}
With a Java Servlet Application (part of, but not the total sum of Java EE - Java Enterprise Edition), applications have servlets under what is called a "context path". This "context path" has to be specified in order to map any request to the application.
Apache Tomcat makes this context path pretty easy to configure, either via server.xml (not recommended) or individual context files (recommended). Both ways specify where to find your web application directory (an unpacked web application archive, or WAR file) and where to place it on the server at a context path.
As Vlad has already said, if you deploy your war file into Tomcat's webapps directory and have automatic installation on (I believe it is on by default), Tomcat will unpack the .war into a directory under that location and use the war's name as its context path. His example war file is named "helloapp.war", so, with the default settings, it would receive any request to http://localhost:8080/helloapp because its context path becomes helloapp.
Of course, once the request is sent to the context path, something needs to match against it. That's where the web.xml comes in to play. While it is possible to use the root as a matcher (every request to the context path gets handled by the same process), typically a pattern is used (such as *.do, *.action, etc), so that individual requests to the helloapp are easily distinguishable (it's easier to read and debug http://localhost:8080/helloapp/login.action and http://localhost:8080/helloapp/doSomethingElse.action than both being recognized via some parameters and the same path of http://localhost:8080/helloapp in my opinion)
So, the context path gets to your application, then your application has to do a lookup on the web.xml to see where to send the actual request. In your example, if your webapp was deployed at the context path of helloapp, to access it with the proper mapping, you would simply append /hello, so the request becomes http://localhost:8080/helloapp/hello
You are deploying your hello servlet in a webapp. Assuming the webapp is in a folder helloapp or in an archive helloapp.war in Tomcat's webapps directory then your sevlet would be accessible at http://localhost:8080/helloapp/hello
You will either need to rename the package to ROOT.war (or the ROOT directory) or modify the ROOT.xml context.xml file to point to the hello folder.
If you go to /hello/hello I bet you'll see your app. If you're using tomcat, use context.xml.
You may not need to use it for a webapp to work, but if you deploy under tomcat, things just work more coherently when you have a context.xml file.
In /yourtomcatinstall/webapps/hello/META-INF/ create a context.xml file with this information"
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/hello">
</Context>
And change the url mapping of your servlet in web.xml to / and/or /* you can have more than one url mapping for a servlet.

Passing variables to a JRuby application via Tomcat config

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".

Extending spring based app

I have a spring-based Web Service. I now want to build a sort of plugin for it that extends it with beans. What I have now in web.xml is:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/*-configuration.xml</param-value>
</context-param>
My core app has main-configuration.xml which declares its beans. My plugin app has plugin-configuration.xml which declares additional beans. Now when I deploy, my build deploys plugin.jar into /WEB-INF/lib/ and copies plugin-configuration.xml into /WEB-INF/classes/ all under main.war.
This is all fine (although I think there could be a better solution), but when I develop the plugin, I don't want to have two projects in Eclipse with dependencies. I wish to have main.jar that I include as a library. However, web.xml from main.jar isn't automatically discovered. How can I do this? Bean injection? Bean discovery of some sort? Something else?
Note: I expect to have multiple different plugins in production, but development of each of them will be against pure main.jar
Thank you.
I think there is a simpler approach:
In your host application (the webapp) define something like the following contextConfigLocation parameter:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/META-INF/foo/*-configuration.xml</param-value>
</context-param>
The crucial parts are classpath*:as it results in scanning the entire classpath for config files matching the following pattern. If you only use classpath: the lookup will stop at the first file found. It also won't traverse JARs if not starred correctly.
The second crucial part is having at least one non-wildcarded basepath for the lookup to work. This is due to Classloader traits that only reliably returns all resources if they contain a base path (see the Javadoc on PathMatchingResourcePatternResolver for details).
What you now have to do with your plugin projects is place your plugin-configuration.xml in /META-INF/foo/, package that as JAR and place it into your classpath (in case you build with Maven just add the dependency).
On application start Spring will now also pickup all config files from your plugins and build the ÀpplicationContext` from em.
You also might wanna checkout another post I did on application modularity with Spring: How do you make a multi-module spring configuration?
Instead of /WEB-INF/classes/*-configuration.xml, try classpath:*-configuration.xml
You can also list configuration files, each on a new line.
You will have to make sure that main.jar ends up in WEB-INF/lib, if you're not using maven you can do this in eclipse by marking you webapp as dependent on the project that creates the main.jar, via the project properties.

Categories