I have a simple problem: I want to configure an object differently based on whether the object is instantiated within a servlet container, or whether it is instantiated in a stand alone app.
The object is a database connection, and I care about setting query timeouts.
The first solution that I can come up with is:
if (insideServletContainer(this.getClass().getClassLoader()) {
/// do some servlet specific config
}
else {
/// do some standalone config
}
The question is, of course, can I write a reliable method of telling whether the class was loaded within a servlet container. It feels like a hack at best.
The second option is to assume that the default case is a stand alone instantiation, set defaults based on stand-alone configuration, and override them within the servlet context.
So, to sum up my question is: Do you know of a good/reliable mechanism if the class was loaded from within a servlet container? If not, I will have to take the second route.
Nick
This seems like a really bad idea. Instead, why don't you allow the class to take parameters, then let the container or app configure it appropriately?
Setting aside whether or not this is a good idea, I'd suggest looking up java:comp/env, which is only going to be available in an EE server:
try {
new InitialContext().lookup("java:comp/env");
/// do some servlet specific config
} catch (NamingException ex) {
/// do some standalone config
}
An alternate way to do this sort of thing is to have the configuration injected into this class by some sort of bootstrap loader.
In a standalone version, this would be done by the main() method (or something called from it).
In a webapp version, this would be done by a listener or filter invoked configured within the web.xml.
Dependency injection is useful here as it removes the need for your application to check these sorts of things; instead the application is given what it needs.
I would recommend Dependency Injection like #matt b.
As a second option, if it is only the simple case you described and you don't want to add or learn a DI framework to support this feature. You can accomplish the same thing as your current code by using a properties file to load different value based on the environment. You can simply use a different file for each environment and supply a VM arg to indicate which environment you are running.
db_prop.dev
db_prop.stalone
dp_prop.int
db_prop.prod
Then you can load by resource
"db_prop." + System.getProperty("runtime.env")
Related
I'm trying to understand how to control dependency injection in OSGi (specifically Apache Felix as used in Adobe Experience Manager (AEM)). I have a servlet with an #Reference annotation on a field that references an interface -- in my case, it represents a secure document signing provider. I have an implementation class that implements the interface, and it's automatically injected into the servlet.
In the servlet:
#Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private DocumentSigningProvider signingProvider;
...
URL redirectUrl = signingProvider.Sign(...);
and my implementation class:
#Component(metatype=true)
#Service
#Property(name = "service.ranking", intValue = 1000)
public class DocumentSigningProviderDocuSignImpl implements DocumentSigningProvider {
If I write a second implementation, I can control which one is injected via the service.ranking value -- highest number wins. If no ranking is declared on any of the implementations, the oldest wins.
So far, so good -- except that to change the values I need to recompile and redeploy. I need to control this at runtime, or via a configuration file that's tied to the environment or "runmode". I can't see how to do that.
Since the #Component declares metatype=true, #Property annotations within the class generate a control in the OSGi console's GUI. I can use that GUI to change values at runtime. But the service.ranking is declared in an #Property on the class itself, and it doesn't appear to generate a control in the GUI.
In addition, configuration files named after the class provide default values at runtime, and I can have a different config file for each environment or "runmode". This would work for me too; in one environment I can configure a mock implementation, and use a "real" implementation in another environment. But again, these config files seem to work for #Property declarations inside the class, but not on the class.
I've read a number of threads here about this subject but none touch on exposing service.ranking in the OSGi GUI or in config files.
Is there any way to control which class is injected without modifying, re-compiling and re-deploying source code?
In declarative services you can override any service property at runtime by providing a config for the component and setting the property.
So setting service.ranking=1 or similar should actually work.
One thing to note. By default declarative services binds to the first available service and stays with it. So if you want to make sure a service with a higher ranking is used even if it comes later than the one with the lower ranking then you need this option on the consumer side:
#Reference(policyOption=ReferencePolicyOption.GREEDY)
This makes sure DS switches the service if a better one comes later.
If you want to be more specific what service to use on the consumer side you can also use a filter at runtime.
target.signingProvider=(myproperty=myvalue)
I have collected some more hints here.
The question is old hat - what is a proper design to support a configuration file or system configurations across our system? I've identified the following requirements:
Should be able to reload live and have changes picked up instantly with no redeploying
For software applications that rely on the same, e.g., SQL or memcached credentials, should be possible to introduce the change in an isolated place and deploy in one swoop, even if applications are on separate machines in separate locations
Many processes/machines running the same application supported
And the parts of this design I am struggling with:
Should each major class take its own "Config" class as an input parameter to the constructor? Should there be a factory responsible for instantiating with respect to the right config? Or should each class just read from its own config and reload somewhat automatically?
If class B derives from class A, or composes around it, would it make sense for the Config file to be inherited?
Say class A is constructed by M1 and M2 (M for "main") and M1 is responsible for instantiating a resource. Say the resource relies on MySQL credentials that I expect to be common between M1 and M2, is there a way to avoid the tradeoff of break ownership and put in A's config v. duplicate the resource across M1 and M2's config?
These are the design issues I'm dealing with right now and don't really know the design patterns or frameworks that work here. I'm in Java so any libraries that solve this are very welcome.
You may want to check out Apache Commons Config, which provides a wide range of features. You can specify multiple configuration sources, and arrange these into a hierarchy. One feature of particular interest is the provision for Configuration Events, allowing your components to register their interest in configuration changes.
The goal of changing config on the fly is seductive, but requires some thought around the design. You need to manage those changes carefully (e.g. what happens if you shrink queue sizes - do you throw away existing elements on the queue ?)
Should each major class take its own "Config" class as an input parameter to the constructor?
No, that sounds like an awful design which would unnecessarily overcomplicate a lot of code. I would recommend you to implement a global Configuration class as a singleton. Singleton means that there is only one configuration object, which is a private static variable of your Configuration class and can be acquired with a public static getInstance() method whenever it is needed.
This configuration object should store all configuration parameters as key/value pairs.
I have worked most on the legacy projects where i spot this line ctx.lookup("datasource"); many number of times. As per usage I have encountered with Initial context , it is used to get the java object binded with some name in webserver/appserver.
For example, we create datasource thru admin console of weblogic then we can use that object programmaticaly in java program with ctx.lookup("datasource"). If I recall correctly I saw this kind of code during EJB implementation also somewhere where some object that was binded with some name in server itself.
Java docs says When the initial context is constructed, its environment is initialized with properties defined in the environment parameter passed to the constructor. So probably the usage I mentioned earlier, Initial context gets constructed with environment parameters(which probably means objects which admin has created in server like datasource, connection pool if any). This is the just one use I could relate initial context.
Please let me know the if it is correct and right usage of initial context class?
Basically with initial context , we can bind/lookup java object with same name. In case of webserver/appserver probably the objects like datasource,connection pool get binded by the server at the time of start up and we can look up them straightaway?
This looks like a correct use of the context class. In newer EJB implementations you can also use the #EJB and #PersistenceContext annotations. For a deeper understanding read the wikipedia article about Dependency Injection.
I have set up UrlRewriterFilter (Tuckey) with many rules and it is working very good for my servlet. But I want to use the same config to rewrite urls outside servlet - in code that generates e-mails with urls.
So, I need to somehow start UrlRewriter (or some kind of wrapper) to process outgoing url i.e. rewrite them with my outbound-rules already defined in config (urlrewrite.xml).
I would like to use it just like this:
String prettyUrl = urlRewriter.rewriteOutgoingUrl(uglyUrl);
Is this possible at all? How to achieve this goal?
It's open source. You could review it's source code (http://code.google.com/p/urlrewritefilter/source/browse/trunk/src/java/org/tuckey/web/filters/urlrewrite/UrlRewriteFilter.java) and see if the logic is available in standalone class(es) which don't rely on servlet request/response objects. If it is, just use it. Otherwise you can build it yourself based on the original source, reusing as much of the library as possible.
You probably just need to initialize UrlRewriteFilter. Since you have to add this in your web.xml file normally the UrlRewriteFilter config files probably get loaded once. I would try loading this in a static initializer in some wrapper class you define. To define a static initializer all you need to do is within a class have the following:
static {
//Your initialization code goes here
}
This code will only be initialized once, during runtime. For more information please look here:
http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html
Is there something I can call from a POJO to see if the code is currently in an App Server or outside of an App Server?
Something like this (In rough PseudoCode):
System.getRunningEnvironment().equals(Environment.Glassfish)
or
System.getRunningEnvironment().equals(Environment.ApplicationServer)
or
System.getRunningEnvironment().equals(Environment.JavaSE)
If you can change AppServer initialization scripts (take a look at this link):
Add -DRunningInAppServer=true at your AppServer initialization script.
Add -DRunningInAppServer=false at your application initialization script.
Then use this method:
public boolean isRunningInAppServer() {
if ("true".equals(System.getProperty("RunningAppServer"))) {
return true;
}
return false;
}
I don't believe you can do this trivially. And would you want to distinguish between an app server, a web container etc.?
What is the reason for determining this ? To allow your POJOs to behave differently in different environments ? If so then I think this points to an object/component structure that is not quite correct, or at least where the object responsibilities are not clearly defined.
The easiest way is, to check the existence of Java EE/App Server specific classes.
I never used an application server, but maybe you'll be able to achieve this with System.getProperties() / System.getProperty(...)
Consider checking for the current SecurityManager, if your application server uses one.
I don't think there's any way to determine this directly. Yes, as SourceRebel says you could set a system property. Personally I'd avoid doing this, though, as you then have some hidden coupling going on: your function is dependent on a system property that must be set correctly for it to work, but there is nothing clearly defined in the interface to reflect this. I think you'd be far better off to just pass in a parameter that says which it is, and let the caller be responsible to pass in the correct parameter. Then the existence of this parameter can be clearly seen in the function signature, and anyone using it will have a strong clue that they need to set it correctly. Having the caller set it correctly should be trivial, as presumably at some point in the call chain you are either calling from a desktop app or from a web page, and that caller knows which it is.
Some applications server set system properties, JBoss for example:
http://community.jboss.org/wiki/JBossProperties