EJB properties file - java

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.

Related

Store properties in database, but override locally

Currently, we store our application's environment properties in a .properties file in the WEB-INF. We want to move them to a database table. But we still want to specify the jndi name, and when running in our test environment locally, we want to be able to override certain properties just for our workspace for test and development.
Apache commons' DatabaseConfigurator seemed nice, but wouldn't play nice with the jndi name being defined as a property in the file. Nothing I did to ask it to look at the property file first worked.
I decided to subclass apache commons' AbstractConfiguration to try to create a single configurator that would check the file and database as I wished, but again, it didn't really work. Spring wants that jndi name absolutely first, probably because the data source has to be passed into the configurator as a parameter.
How can I get what I am after here? Mostly properties in the database, but those that are in the file override them. And jndi name for the datasource should not have to be hardcoded in the spring config.
Why don't you write a ApplicationContext listener that will read the configuration from your DB and inject them in the JNDI? Then you can override the configuration in the JNDI with a context.xml file that will be placed in the src/local/webapp/META-INF/.
This is how we get this working in our webapp.

How to pass deployment dependant parameters to webapp

In projects I work(ed) on, deployment parameters - such as storage path or DB login - are usually given through a parameter file, which is stored in the war file.
I find that unsuitable because those values needs to be changed each time the webapp is packaged for a different deployment (dev vs prod, change of executing computer). The source code being versioned, this makes it even more bothering.
Is there some better option to pass parameters such as listed above?
By better, I mean:
practical: simple to setup, change and explain to others
separated from the war
as independent as possible to the web container (if dependent, I'm using tomcat in prod)
Edit
I chose the answer of #aksappy to reward the work done in the answer and because it provided several methods using standard tools. However, depending on the context I could go for any other solutions:
method of #Necreaux has best simplicity
method of #Luiggi Mendoza has a good design and is still simple
method of #OldCurmudgeon would be a really good one if the code covered other cases.
You can use a multitude of things based on your environment. Here are somethings which may be considered
Use datasources
The datasources defined in the server context removes the hard wired dependency of managing db configurations and connection pool from the web application. In Tomcat, this can be done as below in the context.xml
<Context>
...
<Resource name="jdbc/EmployeeDB" auth="Container"
type="javax.sql.DataSource"
description="Employees Database for HR Applications"/>
</Context>
Use Contexts
You can configure named values that will be made visible to the web application as environment entry resources, by nesting entries inside this element. For example, you can create an environment entry like this: (Source here). This can be set as context parameters or environment entries. They are equivalent to the entries made in a web.xml or a properties file except that they are available from the server's context.
Use database configurations and load those configuration at ServletContextListener
Another approach which I tend to follow is to create a relational schema of properties in a database. Instead of loading the properties file during server startup, load the properties from the database during start up.
public class ContextInitialize implements ServletContextListener {
private static Properties props;
public void contextInitialized(ServletContextEvent servletContextEvent) {
// connect to DB
// Load all the key values pairs as required
//put this into a Properties object, or create a hashtable, hashmap ..
}
//Getter
public String getProperty(String key){
// get value of key
}
//Setter
public void setProperty(String key, String value){
// set value to a key
}
}
Note: above is just an example.
Use environment variables or classpath variables
Use classpath / path variables in Environment variables and use System.getenv() in your java code to get these values as necessary.
We normally put our web app properties files in the Tomcat home folder. POJOS look on the launch folder. There will be other standard locations for other web servers.
final String tomcatHome = System.getProperty("catalina.home");
if (tomcatHome == null) {
// POJOs look in "."
searchPaths.add(".");
} else {
searchPaths.add(tomcatHome);
webApp = true;
}
An strategy is to pack all the properties and configuration files in an external jar and make this jar a dependency for your application(s): war, ear, etc. Then, you can deploy this jar in a common folder where the application server will load it and make it available for all the applications deployed there. This means that you will deploy the jar with the values for each environment once (or every time you need to change it, but its changes must be slow compared to the changes made to your main artifacts) and you can deploy and redeploy your war or any other project in your application server without problems.
In case of Tomcat, you may deploy this jar inside %CATALINA_HOME%/lib as explained in Tomcat Tutorial. Class Loader Definitions
To consume (read) these files in my application, I just load them like any other resource in my application.
Two strategies I've used:
JVM Parameters -- Custom JVM parameters can be set by the container at startup. This can get a bit verbose though if you have a lot of settings.
Configuration Files -- These can be read by the application. Either the location is hardcoded, put inside the container path, or to get the best of both worlds, specify the location via a JVM parameter.

How to re-initialize beans in spring without application server restart

I am programming service for getting data from database and providing them via REST service. It uses spring mvc. My database connection cofiguration is in property file from where it is loaded by spring as a data source bean during context initialization.
Now my problem is - I want to change configuration in properties file (for example change database info) but I can't afford to restart the application server so the new configuration does not load.
How can I re-initialize spring context or some particular beans so the newly defined properties are used?
If you want multiple data source in spring and need to deciding appropriate data source dynamically at runtime you can do this with AbstractRoutingDataSource provided with spring. You have to implement your lookup key logic for determining data-source in method determineCurrentLookupKey(). With this you can map different beans to different data-sources at runtime. following are few questions relating to this context.
How to programatically change databases in Spring with one DataSource?
Also
dynamically change Spring data source

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.

Get properties files from multiple servlet contexts

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.

Categories

Resources