At the top of the WebSphere log file, I see a couple of lines:
WebSphere Platform 8.5 blah blah running with process name abc\xyz\pqr and process id 1234
Full server name is abc\xyz\pqr-1234
I would like to get the value pqr shown in the above two lines using Java code in my application that runs on the WebSphere server. I found that I could get the values abc and xyz by doing JNDI lookup, based on this answer to another question:
(new InitialContext()).lookup("thisNode/cell/cellname").toString(); // returns "abc"
(new InitialContext()).lookup("thisNode/nodename").toString(); // returns "xyz"
However, JNDI lookup of "servername" does not return pqr or any of the values above, but something else entirely.
How can I get the value pqr (or the entire value abc\xyz\pqr or abc\xyz\pqr-1234, whichever is possible)? I would prefer to get the value by doing a JNDI lookup rather than by using a WebSphere class like com.ibm.websphere.runtime.ServerName as mentioned here, but if that is not possible I can use any solution that works.
I realize there may be questions about why I need to get the value and perhaps even opinions that it may not be a good practice to get that value etc. However, I have a valid and unavoidable reason for doing that.
Here is a link to a document about how to capture a WebSphere namespace dump, including example output, showing entries such as,
(top)/nodes/outpost/nodename
(top)/nodes/outpost/servers/server1/servername
Have you tried a look up of the following?
thisNode/servers/thisServer/servername
Well this answer is not a JNDI solution, however it is a solution to this problem. WebSphere provides class com.ibm.websphere.runtime.ServerName which is used for exactly this scenario. It has bunch of utility methods like:
getDisplayName()
getServerId()
getFullName()
So how to use this class in your project while still being able to deploy project on a non-websphere environments? By checking in runtime if you are running within WebSphere, and if you do, than invoking methods within ServerName.
In order to not pollute your project with unnecessary dependencies to was runtime create a new utility jar project and add dependencies:
com.ibm.ws.runtime-xxxx.jar as provided dependency (part of was or was client)
spring-core-xxxx.jar as runtime dependency
Rest of the solutions are in following two methods withing two classes. One which checks for presence of websphere and other which interacts with it:
import org.springframework.util.ClassUtils;
public class WasInfo {
/**
* #return a map populated with relevant WebSphere names
* if running on WebSphere or empty one if not
*/
public Map<String, String> about() {
ClassLoader currentClassLoader = this.getClass().getClassLoader();
boolean isWebsphere = ClassUtils.isPresent("com.ibm.websphere.runtime.ServerName", currentClassLoader);
if (!isWebsphere ) {
return new HashMap<>();
}
WebSphereConfig wc = new WebSphereConfig();
return wc.resolveServerName();
}
}
import com.ibm.websphere.runtime.ServerName;
public class WebSphereConfig {
public Map<String, String> resolveServerName() {
// expecting 'cell/node/server' pattern
String serverFullName = ServerName.getFullName();
String serverName = ServerName.getDisplayName();
Map<String, String> map = new HashMap<>();
map.put("serverFullName", serverFullName);
map.put("serverName", serverName);
String[] segments = serverFullName.split("\\\\");
if (segments.length == 3) {
map.put("cellName", segments[0]);
map.put("nodeName", segments[1]);
}
}
}
I used Spring's ClassUtils to get rid of some boring code in this example. And for exercise one could invoke ServerName methods using reflections. That would remove a need for import ServerName statement and make code even more "simpler". But idea would remain the same.
Related
I am trying to do one example with ArchUnit where passing the AnalyzeClasses can be dynamic based on for which Adapter Application the test need run.
For Example:
#AnalyzeClasses(packages = "${archtest.scan.package}", importOptions = { ImportOption.DoNotIncludeTests.class, ImportOption.DoNotIncludeJars.class })
public class ArchitectureTests {
}
And from application.properties file it should allow to pass the packages to analyze dynamically, so any application using this Application as Jar library can provide the scan classes in its properties file. As below.
archtest.scan.package=com.example.pkgname
I am not sure what is the right way to pick up the dynamic value from property and pass that into #AnalyzeClasses Annotation. I am looking for some help or any example in this regard.
I don't think that ArchUnit's JUnit 4 & 5 support – in the current version 0.23.1 – allows for dynamic packages configured via an application.properties.
But instead of using #AnalyzeClasses, you can always just invoke new ClassFileImporter().import… and pass any dynamic runtime values you like.
(Note that ArchUnit's JUnit support also introduces a clever cache to reuse imported JavaClasses by multiple #ArchTests, but storing JavaClasses in a static field may be also good enough.)
This actually should be possible using a custom LocationProvider within #AnalyzeClasses. E.g.
#AnalyzeClasses(locations = ApplicationPropertiesLocationProvider.class)
public class ExampleTest {
// ...
}
class ApplicationPropertiesLocationProvider implements LocationProvider {
#Override
public Set<Location> get(Class<?> testClass) {
String packageToScan = readFromApplicationProperties();
return Locations.ofPackage(packageToScan);
}
}
But be aware of caching limitations! The caching mechanism assumes that your LocationProvider is "idempotent", i.e. it always returns the same locations. The caching mechanism will only take the type of the LocationProvider into consideration as cache key. This should not be a problem for a static application.properties as source though.
This morning I fell into a particular case that never happened to me before. I'm developing a Minecraft plugin using the minecraft server API which is usually called NMS with reference to the name of its packages (eg net.minecraft.server.v1_13_R1 for version 1.13).
The main problem with the use of the minecraft server API is that it is difficult to write a cross version code: indeed the name of the packages changes with each new version.
When the plugin only supports two versions it is usually easier to use the interfaces to write two different codes depending on the version. But when you have to support a dozen different versions (and this is my case), it's a bad idea (the plugin would be much too heavy, it would have to import every jar in the IDE, and I would have to redo the code with each new version).
In these cases I usually use reflection but I do not think it's possible here:
packet = packetConstructor.newInstance(
new MinecraftKey("q", "q") {
#Override
public String toString() {
return "FML|HS";
}
},
packetDataSerializerConstructor.newInstance(Unpooled.wrappedBuffer(data)));
As you probably guessed MinecraftKey is a class from NMS and I was told to use Java Dynamic Proxy API. I have never used it and would like to know if you would know a place that would explain to me how to do it simply? If you know of another better method that interests me too!
When I think about it, I think that this is really a lot of trouble for a tiny piece of code x)
EDIT :
My plugin uses the PacketPlayOutCustomPayload (aka plugin messages) to communicate with the mods of the players. It allows me to send a message (a byte []) on a particular channel (a String). But with the 1.13 this String has been replaced by a MinecraftKey (a wrapper for the String that replaces some characters and requires the use of a ":"). This poses a problem when players connect to 1.12 on my 1.13 server so I do not have a choice: I have to override the MinecraftKey object in this case.
I don’t really think using proxy classes is good solution here, it will only make it harder to debug, but if you need something like that you should use library like ByteBuddy: (as java can’t generate proxy for a class, only interfaces are allowed)
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.FixedValue;
import static net.bytebuddy.matcher.ElementMatchers.*;
public class Main {
public static void main(String[] args) throws Exception {
SomeKey someKey = new SomeKey("my", "key");
System.out.println(someKey); // :<
// this class should be cached/saved somewhere, do not create new one each time.
Class<? extends SomeKey> loaded = new ByteBuddy()
.subclass(SomeKey.class)
.method(named("toString").and(returns(String.class).and(takesArguments(0))))
.intercept(FixedValue.value("something"))
.make()
.load(Main.class.getClassLoader()).getLoaded();
someKey = loaded.getConstructor(String.class, String.class).newInstance("what", "ever");
System.out.println(someKey); // YeY
}
}
class SomeKey {
final String group;
final String name;
public SomeKey(String group, String name) {
this.group = group;
this.name = name;
}
public String getGroup() { return this.group; }
public String getName() { return this.name; }
#Override public String toString() {
return group+":"+name;
}
}
But I would just create separate modules in my project, one that does only work with real bukkit API and contains many interfaces to represent NMS types in some normalised and readable way.
And separate modules for each version, then you will not have much code to duplicate, as most of it will be abstracted and handled by that “core/base” module.
Then you can build it as one single fat jar or separate .jar per version.
Other solution might be using some template engines and preprocessors to generate java sources on build time, see how fastutil is doing this:
https://github.com/vigna/fastutil
And yet another solution for simple classes and parts of code would be to use build-in javascript or external script language like groovy to also create this pattern-line but in runtime. But I would use this only for simplest stuff.
Also for just using methods you can just use normal reflections.
You can also always inject into netty and instead of using default packet serializer just write own bytes, then you don't need that key at all.
Is there a way to have different environment variables for different war files in tomcat? I am using a 3rd party war and need to have multiple deployments of the same war but with different environment variables (so it loads different configs).
Its easy if you run two instances of Tomcat independently. I'm assuming here you are talking about the OS environment variables.
You can also set properties in Tomcat for each war/web app. That would let you run two wars in one Tomcat instance. But that's not what you asked.
Ok, total crazy hack idea:
Implement a PropertyPlayHolderConfigurer (or use web.xml from Tomcat) for each app instance and load properties same name as you have for System.properties().
Then, create a delegate Properties class that contains both sets of properties. Then
Properties props = new DelegatingProperties(app1Props,app2Props)
System.setProperties(delegate);
public class DelegatingProperties extends Properties {
private Properties app1Props;
private Properties app2Props;
public DelegatingProperties(Properties app1Props, Properties app2Props) {
this.app1Props = app1Props;
this.app2Props = app2Props;
}
public String getProperty(String prop) {
// begin crazy science
String caller = new Throwable().getStackTrace()[0].getClassName();
// this is where you get creative.
// Do the System.setProperties() above so you can intercept calls to
//getProperty()
// and find out the FQCN of the library class(es) that need these variable
// (use your debugger).
// then implement the logic here to decide which of the 2 property sets you have
// you will query to get the correct results
}
}
These are SYSTEM properties we are talking about and they are meant to apply system wide. Your library was probably developed when it was 1-app-1-jvm (or the developer is a tard which is also likely).
Can I atleast get props for creativity? :)
I'm trying to find a solution for configuring a server-side Java application such that different users of the system interact with the system as if it were configured differently (Multitenancy). For example, when my application services a request from user1, I wish my application to respond in Klingon, but for all other users I want it to reply in English. (I've picked a deliberately absurd example, to avoid specifics: the important thing is that I want the app to behave differently for different requests).
Ideally there's a generic solution (i.e. one that allows me to add
user-specific overrides to any part of my config without having to change code).
I've had a look at Apache Commons Configuration which has built in support for multitenant configuration, but as far as I can tell this is done by combining some base config with some set of overrides. This means that I'd have a config specifying:
application.lang=english
and, say a user1.properties override file:
application.lang=klingon
Unfortunately it's much easier for our support team if they can see all related configurations in one place, with overrides specified somehow inline, rather than having separate files for base vs. overrides.
I think some combination of Commons Config's multitenancy + something like a Velocity template to describe the conditional elements within underlying config is kind of what I'm aiming for - Commons Config for the ease of interacting with my configuration and Velocity for very expressively describing any overrides, in a single configuration, e.g.:
#if ($user=="user1")
application.lang=klingon
#else
application.lang=english
#end
What solutions are people using for this kind of problem?
Is it acceptable for you to code each server operation like in the following?
void op1(String username, ...)
{
String userScope = getConfigurationScopeForUser(username);
String language = cfg.lookupString(userScope, "language");
int fontSize = cfg.lookupInt(userScope, "font_size");
... // business logic expressed in terms of language and fontSize
}
(The above pseudocode assumes the name of a user is passed as a parameter, but you might pass it via another mechanism, for example, thread-local storage.)
If the above is acceptable, then Config4* could satisfy your requirements. Using Config4*, the getConfigurationScopeForUser() method used in the above pseudocode can be implemented as follows (this assumes cfg is a Configuration object that has been previously initialized by parsing a configuration file):
String getConfigurationScopeForUser(String username)
{
if (cfg.type("user", username) == Configuration.CFG_SCOPE) {
return Configuration.mergeNames("user", username);
} else {
return "user.default";
}
}
Here is a sample configuration file to work with the above. Most users get their configuration from the "user.default" scope, but Mary and John have their own overrides of some of those default values:
user.default {
language = "English";
font_size = "12";
# ... many other configuration settings
}
user.John {
#copyFrom "user.default";
language = "Klingon"; # override a default value
}
user.Mary {
#copyFrom "user.default";
font_size = "18"; # override a default value
}
If the above sounds like it might meet your needs, then I suggest you read Chapters 2 and 3 of the "Getting Started Guide" to get a good-enough understanding of the Config4* syntax and API to be able to confirm/refute the suitability of Config4* for your needs. You can find that documentation on the Config4* website.
Disclaimer: I am the maintainer of Config4*.
Edit: I am providing more details in response to comments by bacar.
I have not put Config4* in a Maven repository. However, it is trivial to build Config4* with its bundled Ant build file, because Config4* does not have any dependencies on third-party libraries.
Another approach for using Config4* in a server application (prompted by a comment by bacar) with Config4* is follows...
Implement each server operation like in the following pseudo-code:
void op1(String username, ...)
{
Configuration cfg = getConfigurationForUser(username);
String language = cfg.lookupString("settings", "language");
int fontSize = cfg.lookupInt("settings", "font_size");
... // business logic expressed in terms of language and fontSize
}
The getConfigurationForUser() method used above can be implemented as shown in the following pseudocode:
HashMap<String,Configuration> map = new HashMap<String,Configuration>();
synchronized String getConfigurationForUser(String username)
{
Configuration cfg = map.get(username);
if (cfg == null) {
// Create a config object tailored for the user & add to the map
cfg = Configuration.create();
cfg.insertString("", "user", username); // in global scope
cfg.parse("/path/to/file.cfg");
map.put(username, cfg);
}
return cfg;
}
Here is a sample configuration file to work with the above.
user ?= ""; // will be set via insertString()
settings {
#if (user #in ["John", "Sam", "Jane"]) {
language = "Klingon";
} #else {
language = "English";
}
#if (user == "Mary") {
font_size = "12";
} #else {
font_size = "10";
}
... # many other configuration settings
}
The main comments I have on the two approaches are as follows:
The first approach (one Configuration object that contains lots of variables and scopes) is likely to use slightly less memory than the second approach (many Configuration objects, each with a small number of variables). But my guess is that the memory usage of either approach will be measured in KB or tens of KB, and this will be insignificant compared to the overall memory footprint of your server application.
I prefer the first approach because a single Configuration object is initialized just once, and then it is accessed via read-only lookup()-style operations. This means you don't have to worry about synchronizing access to the Configuration object, even if your server application is multi-threaded. In contrast, the second approach requires you to synchronize access to the HashMap if your server application is multi-threaded.
The overhead of a lookup()-style operation is in the order of, say, nanoseconds or microseconds, while the overhead of parsing a configuration file is in the order of, say, milliseconds or tens of milliseconds (depending on the size of the file). The first approach performs that relatively expensive parsing of a configuration file only once, and that is done in the initialization of the application. In contrast, the second approach performs that relatively expensive parsing of a configuration file "N" times (once for each of "N" users), and that repeated expense occurs while the server is processing requests from clients. That performance hit may or may not be an issue for your application.
I think ease of use is more important than ease of implementation. So, if you feel that the second approach will make it easier to maintain the configuration file, then I suggest you use that approach.
In the second approach, you may wonder why I put most of the variables in a named scope (settings) rather than in the global scope along with the "injected" user variable. I did that for a reason that is outside the scope of your question: separating the "injected" variables from the application-visible variables makes it easier to perform schema validation on the application-visible variables.
Normally user profiles are going into a DB and the user must open a session with a login. The user name may go into the HTTPSession (=Cookies) and on every request the server will get the user name and may read the profile from the DB. Shure, the DB can be some config files like joe.properties, jim.properties, admin.properties, etc.
Does anyone know of a method to load a properties file, and dynamically create Strings with identical names to the key value?
I'm trying to clean up my code by moving all the system messages etc out of the logic and into a properties file, but want to avoid having to have a class consisting of dozens of lines like the following:
final String COMMS_ERROR = properties.getProperty(COMMS_ERROR);
An example of what I'm trying to achieve:
for (String key : properties.getPropertyValues()) {
final String <key> = properties.getProperty(key)
}
Obviously this won't work, the compiler will throw a fit. But I'm wondering if there's an elegant solution to do the same thing - create new Strings using the key names from the properties file - be it via a separate library or in my own code.
One solution I've thought of is to populate a HashMap with the keys/values from the properties file, but then that would mean less elegant code in the form of:
import com.x.y.messages;
...
throw new Exception(HM.get("COMMS_ERROR"));
Where HM is the HashMap located within com.x.y.messages...
Ideally I just want to be able to do:
import com.x.y.messages;
....
throw new Exception(COMMS_ERROR);
Any thoughts/advice appreciated.
If those properties can change after compilation (if not, then why would they be used) you'd not have any chance to create AND use those strings dynamically. Sure, there are ways to dynamically create code (like AOP runtime weaving) but that code would not be usable in the normal compilation process.
So how would the compiler know that COMMS_ERROR actually exists in this line throw new Exception(COMMS_ERROR);? It can't and thus you'd need to go for the HashMap approach. Note that Properties is actually a Map<String, String> (ok, it is a Hashtable<Object, Object> as of Java 6 but it acts like a Map<String, String>), thus there's no need to create a new one.
Edit: what you could do is use static imports like this:
package yourpackage;
public class Props
{
private static Properties props;
public static String prop(String prop)
{
return props.getProperty( prop );
}
}
Use it like this:
import static yourpackage.Props.prop;
....
prop("someKey");
Note that static import has its drawbacks like looking as if the methods were part of the class it uses, so I'd just like to provide an alternative and let you decide whether to use it or not.
What is wrong with
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources( "com/x/y/message.properties" );
while( resources.hasMoreElements() ) {
URL url = resources.nextElement();
Properties p = new Properties();
p.load( url.openStream() );
...
}
i dont see why store data from Properties to HashMap
import com.x.y.messages;
....
throw new Exception(p.getProperty("COMMS_ERROR"));
You cannot declare local variables on the fly but you can use a map:
Map<String, String> messages = new HashMap<String, String>();
for (String key : properties.getPropertyValues()) {
messages.put(key, properties.getProperty(key));
}
to use them:
throw new Exception( messages.get( "KEY" ) )
See http://download.oracle.com/javase/6/docs/api/java/util/Map.html
But in fact as Thomas pointed out above you don't need a new HashMap just
throw new Exception( properties.getProperties(key) );
I have previously written helper classes myself that kept a Properties file in sync with a Constants class. But that only works if you stick to conventions.
Lets say you have a class like this:
public final class Constants{
private Constants(){}
public static final String SOME_PROPERTY_NAME = "some.property.name";
public static final String THIS_ONE_NOT_SET_YET = null;
public static final String PROPERTY_NOT_DEFINED = "property.not.defined";
}
and a property file like this:
some.property.name=Hello World
no.constant.for.this.yet=Hello again
What my helper class would do was to loop over all properties and all constants, make matches and identify those that didn't correspond to anything.
So in this case:
a)
In Constants.java,
public static final String THIS_ONE_NOT_SET_YET = null;
would be changed to
public static final String THIS_ONE_NOT_SET_YET = "this.one.not.set.yet";
and in the properties file, this line would be introduced:
this.one.not.set.yet=
b)
in the properties file, this line would be added
property.not.defined=
c)
In Constants.java, this line would be added:
public static final String NO_CONSTANT_FOR_THIS_YET = "no.constant.for.this.yet";
It's not perfect, but that way you get pseudo-compile-time safety. You compile against constants, and your helper keeps those constants in sync with he properties.
Obviously this approach gets a lot more complicated if you have more advanced scenarios.
E.g.
Properties starting with "foo." being stored in "foo.properties" while properties named "bar." are being stored in "bar.properties"
Internationalization: Now you have foo.properties, foo.properties.es, foo.properties.de etc. Keeping that in sync is a major nuissance.
Perhaps one thing to consider would be to have your constants class dynamically created from one or more properties files during the build process. Your code generator (a Main class, a Groovy script or even a shell script) would basically just have to do this (pseudocode):
properties = readProperties()
writeClassHeader()
for prop : properties
writeln "public static final String "
+ prop.name.upperCase().replace(".","_") + "= \"" + prop.name + "\";"
writeClassFooter()
I'm not aware of a tool that would do this, and it doesn't fit the normal Java way of doing things. (In Java you can't add new variables on the fly ... unlike Javascript for example.)
It is theoretically possible to implement something along these lines, but it would probably entail generating and compiling a class for each kind of property file, and recompiling the rest of your code against these classes APIs. Unless you've got huge numbers of these property files, it is easier to code the classes by hand. (And if you do have huge numbers of these properties files, I would be inclined to see if there was a better way to handle the information in those files.)
Yeah that's what I was hoping for - a library that would contain the necessary magic
Unfortunately no ordinary library could do this. The generation / recompilation has to happen at build time. (A library could generate the classes at runtime and even compile and load them. But getting it to recompile the rest of your application at runtime is at best difficult, and typically impossible ... because the source code is not available.)
It looks almost exactly what my library does! Check it out: http://owner.aeonbits.org
Example:
# Properties file (call it the same name as the Java class and put
# it in the same package
port=80
hostname=foobar.com
maxThreads=100
//properties mapper interface
public interface ServerConfig extends Config {
int port();
String hostname();
int maxThreads();
}
// how you use it:
ServerConfig cfg = ConfigFactory.create(ServerConfig.class);
System.out.println("Server " + cfg.hostname() + ":" + cfg.port() + " will run " + cfg.maxThreads());
But, you can do much more with OWNER library.