Java Spring #Value annotation, and parameters - java

So, I have an environment property that is supposed to reflect what environment my app is running in.
#Value("${environment}")
private String environmentName; //This will be set as sandbox, staging, production
I also have a feature flag (feature is called 'superFeature.enable') that should be set based on what environment the app has been deployed in.
//Config file
superFeature.enable.sandbox=true
superFeature.enable.staging=false
superFeature.enable.production=false
//#Service annotated class containing call to configuration
#Value("${superFeature.enable.{environment}:false}")
private boolean isSuperFeatureEnabled;
At the moment, when I run my app in my sandbox environment, isSuperFeatureEnabled is always false. Is my syntax correct for the above code snippet? Is there something I'm missing?

Shouldn't you have put
#Value("${superFeature.enable.{environmentName}:false}")
there?
This is just a guess, I'm afraid. It looked like an inconsistency there. But then, I don't know in which context and order these two statements above are executed, so I don't know where which variables are known.
I would suggest getting some more information first. Like, what happens if you replace the {environment} with the expected string for your environment, can you get the environment value in your code at that point. I don't know if it is even possible to have this kind of double indirection at all.

It should be the following(environment also enclosed within placeholder syntax starting with $) :
#Value("${superFeature.enable.${environment}:false}")

Related

Is it possible to modify experiment parameter values after a model is run?

I'm following the Integrating AnyLogic Models with External Java Applications module and while I am able to change parameters before I run the exported java application, it seems the values become immutable once the model runs. Is there a way to dynamically modify parameter values at runtime?
Below is a snippet of my Java code:
final Simulation s = new Simulation();
IExperimentHost host = new ExperimentHost(s);
s.parameter1 = 50;
s.setup(host);
host.launch();
s.runTheModel();
s.parameter1 = 100;
The result is that parameter1 never changes from 50 to 100. Is there a way to circumvent this?
Try set_parameter. The help menu talks about this a little bit.
Edit:
Your original question was not directly linked to running as an external java application, but I think this could really simplify things. When you export your java application, look at the .bat file. You will see what the command line would look like to run the model. What we do when we are running from an external application is just have the external application call this command line, as opposed to what AnyLogic discusses in the help menu. A significant advantage of this is that you can easily mimic in the development environment what is going on in the exported model.
Ask your self why you are changing these parameters at runtime. Is it because of a read statement and you just don't have the data prior to the model run? If so, think about the order you instantiate your objects and don't start them until after you have the variables set that you want to use. This can be done by passing in parameters to main, setting database values, or having the main agent do various read statements.
Is it that you just want items to change over time? If so, consider variables, instead of parameters. Consider other objects that may allow you to more easily change flow. For example, does a valve before a pipeline or other sequence give you the level of control that you want?
At this point, would probably need more detailed information about what you are trying to accomplish / the system you are modeling, in order to provide any more specific advice.

Change #PropertySource value in run time

How can I change the value of #PropertySource in run time when the junit test case runs. For example,
I want to replace the value of below,
#PropertySource(value = "file:${app.deploy.env}/sample/mine.properties", ignoreResourceNotFound = true)
with
value = "classpath:sample/mine.properties"
when junit test runs.
You can do that if you really want to but I'd not recommend you to do that this way. You first need to figure out which PropertySource contains the value. Since you have that annotation in your example, a PropertySource will be added to the regular ones, probably as the first instance.
You can inject the Environment in a managed bean where you want to make that change as a ConfigurableEnvironment and retrieve the PropertySource via un call to getMutablePropertySources() on the environment.
Having said that. Why? How is changing such fundamental property of your application is representative of what is going to happen in your app. It looks like you are using the Spring runner and you'd like to start your app with different settings in different test methods. If that's what you want to do, do not use the runner but manage the context yourself, it's really not that hard.
For instance, here are JMS-related tests that change the Environment to test various scenarios. You can easily load the context with a specific set of keys and a #After method makes sure to shutdown the context for each test.
We use this pattern quite a lot in Spring Boot. As a matter of a fact, I have a JUnit rule that facilitates all that on my todo list for months now.

Understanding the practical uses of InitialContext in java?

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.

Detect if running in servlet container or standalone

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

Can Java Code tell if it is in an App Server?

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

Categories