Get properties files from multiple servlet contexts - java

I'm working on a web application that is spread over multiple contexts running inside one instance of tomcat. The contexts are marked with crossContext="true" so that we can share some of the jsp between the different contexts. There is also a set of common classes that are part of the common.loader for tomcat. We are to far away into the project to change this structure so please be sensitive to this structure when answering the question.
What I would like to do is get all the resources, say com.something.messages, that are present in all the different contexts. Is this at all possible? Should I record the class loader for each context created and use it to load the resources? What do you recommend?

If you're already on Servlet 3.0, then you could use ServletContext#getClassLoader() to obtain the servlet context's own class loader:
ServletContext otherContext = servletContext.getContext("/other");
ClassLoader otherClassLoader = otherContext.getClassLoader();
// ...
(if this throws a security exception, edit the policy file accordingly)
You could then pass this class loader into for example ResourceBundle#getBundle():
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, otherClassLoader);
// ...
If that's not possible due to various reasons (e.g. not using Servlet 3.0 yet, or not willing to fiddle with policy files (very reasonable...), etc), then your best bet is to give each web application its own ServletContextListener which loads the desired bundle and stores it as an attribute of the ServletContext during the contextInitialized() method. This way you can just get it as an attribute the usual way.

Related

Convert traditional projects to spring boot, without changing applicationContext.xml, dispatcher-servlet.xml & tomcat's context.xml

The background & requirements are:
there are a lot of old projects which have an applicationContext.xml and one or more dispatcher[-XXX]-servlet.xml. We hope those projects can still works while using spring boot(we developed a deployment tools to deploy spring boot applications, but the old projects are still deployed manually). But, #SpringBootApplication can't build the contexts as they were. And rewriting them into codes one by one costs too much, I think.
In those project, we use an extended RequestMappingHandlerMapping, so we can't use the native MVC.
the context.xml of tomcat, which contains jndi definitions, is maintained by OPs. We have to load it just like tomcat does.
i can't find where to set welcome file, which were set in web.xml
I currently using:
#Configuration
#ImportResource({"classpath:/applicationContext.xml", "classpath:/dispatcher-servlet.xml"})
Those simple projects without using jndi can startup.
But as my understanding, in this case, the applicationContext and dispatcher-servlet are in the same level(dispatcher-servlet should the child of applicationContext, isn't it?). So, i can't even ensure this one works properly.
We did a similar thing about a year ago and your setup was more or less the same as ours and importing those XML files did the trick; the only thing we had to do was to ensure our application class was in a different package hierarchy in order to avoid conflicting/duplicate bean definitions due to its inherent #ComponentScan.
And having dispatcher servlet and application context in the same context won't cause any issues - yes, dispatcher servlet's context is usually defined as a separate context and is a child of the more broad applicationContext but what most people fail to grasp is that that separation only matters if your application wants to have more than one dispatcher servlet, which is rarely the case any more, if it ever was.
In case of multiple dispatcher servlets it was a must to enable them to have different WebMVC configurations, and applicationContext was there to allow you to share common beans and configuration between your servlet contexts so that you don't have to do the same work twice.

EJB properties file

In my project I have 2 modules, a ejb and a war module. In the war module i have a properties file that is processed when I start the web application (by a listener). For each property in this properties file, i add it to the servlet context.
So, my question is: is it possible to access this properties, in the servlet context, from a enterprise java bean in the ejb module? I want to do something like this, but in a ejb:
ServletContext sc = myservlet.getServletContext();
String xpto = sc.getAttribute("my-attr");
If this is not possible, what is the alternative?
Thanks!
P.S I'm using netbeans and glassfish.
ServletContext is always loaded ahead in the Servlet lifecycle loading. Ref to this link. As you see the Listeners are loaded after the ServletContext is loaded when application starts. You can have your code in the listener class that extends ServletContextListener. Ensure you are extending correct Listener as given in the link.
In your situation, One of the alternative is to have a Singleton class load all the properties from the properties file. for ex: ApplicationPropertiesLoader class can have a Properties map attribute to store the key value pairs of that property file. This class can have a getProperty method that always refer to its internal Properties.
In your servlet class refer to this singleton class to load the properties as required.
Speaking of alternatives, it might be worth a thought to use configuration stored in database, at least if you already have a database connection in your application and have control over the database schema.
We use this technique in all our web applications, mainly for two reasons:
Changes to a property can be done during runtime without monitoring file changes, they can be done by the application itself and one does not need to know a path outside of the deployed application.
Properties can have additional information, such as a type (e.g. number, date, string), a default value, a comment or a user who changed it.
For implementing it, you'll create an application-scoped component which accesses the database properties for the rest of the application.

Difference between javax.servlet.ServletContext and javax.naming.Context

As I knew, Java ServletContext and Context Objects are common used inside Java EE program development. However, I'm not quite sure about what are the differences between them, especially the Context Class usages.
From what I understood, ServletContext is the Object which contains all initializations read from Web.xml so that all servlets in the web application can share those global configurations.
On the other hand, I usually only used Context Object when I needed to dynamically establish database connection with JNDI lookup. Beside that, I'm not clear about other possible usages of this class.
My main concern is does the "context" word of both ServletContext and Context classes represent the same thing or component inside web application?
From the ServletContext javadoc
Defines a set of methods that a servlet uses to communicate with its
servlet container, for example, to get the MIME type of a file,
dispatch requests, or write to a log file.
Basically it's an accessor to the servlet environment. Anything that is relevant to the servlet, you can get it from there. It's really only useful with a Servlet Container.
The JNDI Context javadoc
This interface represents a naming context, which consists of a set of
name-to-object bindings. It contains methods for examining and
updating these bindings.
This is an interface to a resource. You configure a resource with a some identifier which you can retrieve through this interface. You are not limited to using this only in a Servlet Container. For example, you might store a list of connected devices on your network in an LDAP repository. To access this repository, you could write custom code implementing the protocol and interacting with an LDAP server or you could use the LdapContext class, which implements the Context class. Or, you could use it to lookup a JDBC DataSource.
Don't let the fact that they have the same name bother you. They have different goals.
This answer might be of help for when you see Context in a different context.

Remap image requests in a web application (tomcat) with spring for an absolute path

i'm trying to find a way remap a path to an absolute one in order to retrieve images stored in the server filesystem, i'm also using spring mvc but the <mvc:resource> can't map absolute paths, and i can't find a nice way to do this with spring controllers
i.e. I need to map all the image requests from /images/** to /root/var/img/**, in this way when a client browser try to load an image of the page, every images stays in the path above mentioned
You can create a new context with docBase referencing to your folder (/root/var/img) It should look like this:
<Context path=”/images” docBase=”/root/var/img/” ... >
</Context>
Refer to Tomcat context configuration documentation for more details (e.g., for Tomcat 6: Apache Tomcat Configuration Reference: The Context Container).
Introduction to this document lists possible places where context elements can be defined.
EDIT
As I mentioned in comments, Spring-specific way to do this without creating any new context seems to be using RedirectView (link to Spring v2.5 JavaDoc). According to JavaDoc:
"View that redirects to an absolute, context relative, or current
request relative URL, by default exposing all model attributes as HTTP
query parameters."
EDIT2
It seems I've misunderstood RedirectView purpose, which is a good old URL redirection. Thus, answer by #Jens should be more appropriate (+1). I still wonder if there's an existing standard solution in Spring (what I originally thought RedirectView would do..) It's not like there's much code to write, but still :)
EDIT3
After reading more on this topic, I found out that <mvc:resources> is able to do this (i.e., mapping resource using not only relative path, or classpath), you just need to correctly configure location using file: prefix . In fact, there's already answer on SO that explains exactly what you need to do: Spring : serving static resources outside context root
not sure if I am getting that right but I think the common way to do that is to set up a controller which is mapped on the requests to /images/:
#RequestMapping(value ="/images/")
public void fetchImage(#RequestParam String id, HttpServletResponse response)
Then the controller can load the requested image from a configured directory like "/root/var/img" and write it the the OutputStream of the response. E.g:
org.apache.commons.io.IOUtils.copy(fileInputStram, response.getOutputStream())
In addition you have to set the correct mime type etc. in the response.
Jens

Java, NetBean : Access web.xml context parameters from Web Service method?

I am new to java so excuse my lame questions:)
I am trying to build a web service in Java NetBeans 6.1 , but I have some troubles with configuration parameters ( like .settings in .net).
What is the right way to save and access such settings in a java web service.
Is there a way to read context parameters from web.xml in a web method?
If no what are the alternatives for storing your configuration variables like pathnames ?
Thank you
Is there a way to read context parameters from web.xml in a web method?
No, this is not easily done using the out-of-the-box. The Web Service system (JAX-WS) has minimal awareness of the Servlet engine (Tomcat). They are designed to be isolated.
If you wanted to use the context parameters, your web service class would need to implement ServletContextListener and retrieve the desired parameters in the initialization parameter (or save the context for later use). Since the Servlet engine and JAX-WS would each have different instances of the object, you'd need to save the values to a static member.
As Lars mentioned, the Properties API or JNDI are your best bets as they're included with Java and are fairly well-known ways to retrieve options. Use Classloader.getResource() to retrieve the Properties in a web context.
If you are using servlets, you can configure parameters in web.xml:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
These properties will be passed in a ServletConfig object to your servlet's "init" method.
Another way is to read your system's environment variables with
System.getProperty(String name);
But this is not recommended for other than small programs and tests.
There is also the Properties API if you want to use ".properties" files.
http://java.sun.com/javase/6/docs/api/java/util/Properties.html
Finally, I believe looking up configurations with JNDI is pretty common when developing modern web service applications, Netbeans and app containers have pretty good support for that. Google it.
MessageContext ctx = MessageContext.getCurrentThreadsContext();
Servlet wsServlet = (Servlet) ctx.getProperty(HTTPConstants.MC_HTTP_SERVLET);
ServletConfig wsServletConfig = wsServlet.getServletConfig();
ServletContext wsContext = wsServletConfig.getServletContext();
I think the correct answer is ... as always ... "It depends". If you are just running a small implementation with a single server then it depend much on the WS technology you want to use. Some make the servlet context and the context-params easy to access, others don't, in which case accessing properties from a properties file may be easier. Are you going to have an array of servers in a load balanced environment with high traffic where updating the setting for all servers must be instant and centralized in-case of fail-over? If that's the case then do you really want to update the config files for all servers in the farm? How do you synchronize those changes to all those servers? Does it matter to you? If you're storing path-names in a config file then you probably intend to be able to update the path-names to another host in case certain host goes down ("\file_server_host\doc_store" --> "\backup_file_server_host\doc_store") in which case is may actually be better to fail-over using DNS instead. There are too many variables. It really depends on the design; needs; scale of the app.
For simplicity sake, if you just want a simple equivalent of a .settings file then you want a .properties file. Here is an example where I have recently used this in a project: https://github.com/sylnsr/docx4j-ws/blob/master/src/docx4j/TextSubstitution.java

Categories

Resources