Configurable Values in a servlet - java

We have a small Provisioning server which only hosts servlets. Hosted on tomcat. There are few values hardcoded in the servlet which i want to make configurable or external, so that they can be modified without changing the servlets.
Can anyone please suggest what are my Options?

There are a few options:
If the values are servlet specific, you can configure them as Servlet Init-Parameter, in the deployment descriptor (The web.xml file):
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
<init-param>
<param-name>${param-name}</param-name>
<param-value>${param-value}</param-value>
</init-param>
</servlet>
And get them using ServletConfig#getInitParameter(String):
getServletConfig().getInitParameter(paramName);
If the values are web-app specific, you can configure them as Context parameter:
<web-app ...>
<context-param>
<param-name>${param-name}</param-name>
<param-value>${param-value}</param-value>
</context-param>
</web-app>
And get them using ServletContext#getInitParameter(String):
getServletContext().getInitParameter(paramName);
Another option is to have those values in a properties file, and load values from it in the servlet. You can add the properties file to the Web-App classpath (you can put it inside the /WEB-INF/classes folder, or if you are using Eclipse IDE, just put it inside the /src folder, and load it as resource:
Properties props = new Properties();
props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("webapp.properties"));
See Also:
Where to put configuration file in JSP-Servlet Web Application

Options I can think of :
Define them as servlet init parameters in DD(web.xml) or using annotation , if they are specific to Servlet. Look at this Oracle tutorial
Define them as context parameters in DD(web.xml) or using annotation , if they are common for the entire web app.
Define them in an external properties file . You can then load the properties file kept in the classpath.
Java EE 7 tutorial - Servlets (Servlet 3.1)
P.S: I have just given you pointers , you can get the examples of how to achieve that , easily in internet.

You can provide init params to a servlet, which can be configured in your web.xml. This tutorial should help you achieve what you need:
http://www.javatpoint.com/servletconfig

As all said there are many ways.This is Another approach(This is what I am doing right now)
A Constants Class (Public Static String constants)
A XMl file called properties.xml for example veriosn name,branch name etc
<property name="version">XX..XX</property>
<property name="branch">XX.13.</property>
in web.xml
<servlet>
<servlet-name>StartUpServlet</servlet-name>
<display-name>StartUpServlet</display-name>
<servlet-class>com.nextenders.server.StartUpServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
That servlet executes when you start your tomcat
And my StartUpServlet
public class StartUpServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public void init() throws ServletException {
super.init();
setVersion(); //I'l parse that file and assign constants.And use else where
}
So with out touching the App,change properties in xml and restart the App.

Related

Deploying Servlet on Tomcat 8.0.30

I am trying to deploy a compiled Servlet class onto Apache Tomcat server 8.0.30.
But i get the following exception :
javax.servlet.ServletException: Error instantiating servlet class HelloWorld
java.lang.ClassNotFoundException: HelloWorld
My tomcat webapps/ROOT/ folder did not contain the classes folder so i created one and copied HelloWorld.class into it. I added the following lines inweb.xml :
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<display-name>Welcome to Tomcat</display-name>
<description>
Welcome to Tomcat
</description>
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
</web-app>
Can anyone tell me what am I doing wrong?
#wero : This is the content of my HelloWorld.java :
// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
// Extend HttpServlet class
public class HelloWorld extends HttpServlet {
private String message;
public void init() throws ServletException
{
// Do required initialization
message = "Hello World";
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// Set response content type
response.setContentType("text/html");
// Actual logic goes here.
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");
}
public void destroy()
{
// do nothing.
}
}
You need to put the files into the correct places. Java class files need to be placed into WEB-INF/classes:
webapps/ROOT/WEB-INF/web.xml
webapps/ROOT/WEB-INF/classes/HelloWorld.class
Then start Tomcat and look if there are errors in the Tomcat log.
When tomcat had been started there were not class file in your app. Tomcat is loading classes during deployment on startup or if you manually deploy it at runtime. After that the context should be reloaded. You can't just copy your classes to the tomcat webapps folder without loading them.
Read Tomcat docs how to deploy your application.
Deployment is the term used for the process of installing a web
application (either a 3rd party WAR or your own custom web
application) into the Tomcat server.
Web application deployment may be accomplished in a number of ways
within the Tomcat server:
Statically (the web application is setup before Tomcat is started)
Dynamically (by directly manipulating already deployed web applications (relying on auto-deployment feature) or remotely by using
the Tomcat Manager web application)
The Tomcat Manager is a web application that can be used interactively
(via HTML GUI) or programmatically (via URL-based API) to deploy and
manage web applications.
There are a number of ways to perform deployment that rely on the
Manager web application. Apache Tomcat provides tasks for Apache Ant
build tool. Apache Tomcat Maven Plugin project provides integration
with Apache Maven. There is also a tool called the Client Deployer,
which can be used from a command line and provides additional
functionality such as compiling and validating web applications as
well as packaging web application into web application resource (WAR)
files.
Got it. The classes folder I created was "C"lasses where tomcat expects "c"lasses.

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

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.

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.

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

Categories