Environment : ADF application running on WebLogic Server 11gR1 - JDeveloper 11.1.1.7
Can I update and load .properties file on application run-time without restarting my weblogic server? If so please suggest how I can proceed with this requirement.
I haven't tried this, but still here it goes:
Create a method in some backing bean, callable only from an administration page. This method would look like:
public void clearResourceBundleCache() {
ClassLoader cl = this.getClass().getClassLoader();
ResourceBundle.clearCache(cl);
}
Or even simpler:
public void clearResourceBundleCache() {
ResourceBundle.clearCache();
}
(See relevant docs)
To use this you would have to (1) replace the .properties files you want to change in the file system of the server and (2) call this method.
More sofisticated solutions would involve the ResourceBundle.Control (docs).
Related
I built a simple Java web application. It provides a series of RESTful APIs for the user to carry out certain operations on a Java DB through a web interface. I used NetBeans environment during the development, and Glassfish for testing.
Now that I finished it, I would like to be able to deploy it on another machine using binaries (although as for now I use the same machine until I learn how to do it).
I installed Tomcat 7, and moved the .war file into Tomcat's webapp folder. The application deploys. Thereafter I try to read some data from the databse using a button I created just for this, but get the following error
I am not sure what went wrong, but I have two theories.
1) The web application cannot connect to the database. Yet when I attempted to run the application again, after starting JavaDB from NetBeans, there was no difference.
2) Somehow, the application cannot reach the Node service. I assumed that there will be no need to change the API links while moving the app, but perhaps I was wrong.
Or maybe there is some other issue I did not consider? I will be grateful for any advice about how to properly deploy such an application.
EDIT: The issue was solved by using TomEE.
The error is come from your application server of choice.
TomCat is only a servlet container (means it only support Servlet/JSP).
Any other feature (JAX-RS, CDI etc) require a Java EE certified server e.g. GlassFish, WildFly,Payara, WebLogic, OpenLiberty or TomEE.
TomEE could be your best bet if you want to use TomCat in your production or test environment, it is basically TomCat + Java EE other feature.
EDIT:
TomEE don't have a GUI for JNDI datasource configuration like GlassFish, you need to edit conf/tomee.xml
<Resource id="myDataSource" type="javax.sql.DataSource">
jdbcDriver = org.apache.derby.jdbc.ClientDriver
jdbcUrl = jdbc:derby://localhost:1527/dbname
userName = app
password = app
</Resource>
And in your java code:
#Path("resources")
#Stateless
public class MyResources{
#Resource(name="myDataSource")
DataSource dataSource;
#GET
public Response SomeMethod(){
//Do stuff here
}
}
You can check here for more detail configuration on data source.
I've already spent more than 2 days trying to make this work without any result. The server is WebLogic 12c with embedded Coherence server. It is important to mention that I do not run Coherence in standalone mode, instead it starts automatically alongside the application server that has access to Coherence via JNDI context. I am trying to implement POF serialization approach using PortableObject interface to serialize certain objects I save in Coherence. I've also created the corresponding pof-config.xml registering the objects I'm planning to serialize. The only problem is: How do I add the override to the coherence class path?
According to http://docs.oracle.com/cd/E24290_01/coh.371/e22837/gs_config.htm#COHDG5014 I can use the following system property:
java -Dtangosol.pof.config=MyPOF.xml -cp COHERENCE_HOME;COHERENCE_HOME\lib\coherence.jar com.tangosol.net.DefaultCacheServer
The only problem here is that I have no idea which sh/cmd file to edit, since all edits I made to the files in Oracle_Home\coherence\bin\ had no effect.
Also the same article says that there is a way to confirm the pof-config override:
The output for a Coherence node indicates the location and name of the POF configuration deployment descriptors that are loaded at startup. The configuration messages are among the messages that display after the Coherence copyright text is emitted and are associated with the cache service that is configured to use POF. The output is especially helpful when developing and testing Coherence applications and solutions.
Loading POF configuration from resource "file:/D:/coherence/my-pof-config.xml"
But I couldn't find any of the mentioned lines in the logs produced by the server instance.
Any ideas?
Instead of editing files inside of your Oracle_Home, try the following inside of the weblogic admin console:
Login to admin console
Servers link -> Server Name
Click the Server Start tab
Edit the Arguments: text box and add in -Dtangosol.pof.config=MyPOF.xml
You can also change the classpath, Class Path: box, here if you need to
Every time your server starts it should have that property. If you are not using the nodemanager to start your server, you should do the following instead. Keep in mind this will change the properties for every server in your weblogic domain:
Navigate to your <domain home>/bin directory
Edit startWebLogic.sh/cmd
Edit the JAVA_OPTIONS= line and add in -Dtangosol.pof.config=MyPOF.xml
You can also change the classpath CLASSPATH= here if you need to
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.
I have a web application which I wish to configure via settings in an external folder (external to the container and to the .war file). Therefore I want to inject just a single setting into my webapp which is the root folder of my configurations. The reasons for doing this are so that the maintenance team can update configuration settings in nice plain text files without having to re-deploy the war file.
My question is, what is the best way to parametrize a web application in the case of just a single configuration setting. I know I can use a JVM arg and then detect it from my initialization servlet. Ideally, I'd like something that I can put in the server.xml (not the web.xml file) that can be programmatically acquired from my ServletContextListener.contextInitialized(ServletContextEvent paramServletContextEvent) method.
Is there a way to do this using the ServletContextListener approach or is another way?
We are using -Dconfig.location=/foo/bar/config.properties and it works fine. It's a JVM arg, so it goes to the startup script.
You can register properties via JNDI in server.xml, but I'm not convinced this is a better option. server.xml or catalina.sh - both are container-level
In development I use jetty as the servlet container. I have the following development configuration:
master project which has wabapp directory
derived project which overrides some of the files in webapp directory
The master project webapp can be started in development mode thanks to providing appropriate WebAppContext to jetty.
Now I want to start derived project analogously, assuming that when request is made, there is an attempt to:
get resource from webapp directory of derived project
if it does not exists, get it from webapp directory of master project
I know that it is possible to override WebAppContext#getResource() method, however some libraries we use in the project seem to perform IO operations on wabapp directory on their own. For example by calling ServletContext#getRealPath("/"), and then reading files without use of ServletContext#getResource() method. The problem could be solved on lower level by some virtual file system on top of File, however it does not seem to be supported in JDK 1.6, any suggestions?
It seems that using something like ResourceCollection is sufficient:
http://download.eclipse.org/jetty/stable-7/apidocs/org/eclipse/jetty/util/resource/ResourceCollection.html
Unfortunately the GWT's DevMode which I use is based on jetty 6, where ResourceCollection is unavailable. I extended the Resource class myself, and together with own GWT JettyLauncher, and thanks to small trick with setting resourceBase on DefaultServlet via reflection, I was able to serve webapp from two directories simultaneously.
protected void doStart() throws Exception {
setClassLoader(new LauncherWebAppClassLoader());
super.doStart();
ServletHolder holder = getServletHandler().getServlet("default");
Servlet servlet = holder.getServlet();
Field field = servlet.getClass().getDeclaredField("_resourceBase");
field.setAccessible(true);
field.set(servlet, combinedResourceBase);
}