Assume that
I like to manage the configuration of a Java application in form of one or many classes referencing each other which I de/serialize to/from XML because I like the way how that saves a lot of work.
I have a Java project with interfaces and the application packaged in different JARs where interfaces are designed to allow third-parties to implement interfaces and the user to load them at runtime through a fancy GUI. Configuration classes exist in form of interfaces and thus can occur in the serialized XML.
I would like to have one configuration file only controlling all pathes of all resources (I'll probably have to give that up, but I'm curious about your answers). It is searched for in a default location and created with default values if inexisting or can be specified on command line.
How would I go about getting the information about the location of third-party implementations before loading the configuration and still keep one clean configuration file only?
I
parse the XML once using XStream and XStream.omitField for the field which contains instances of configuration classes which need to be loaded from a referenced JAR.
Then I read the partial configuration to the location of the JARs and load the classes.
Then I overwrite the partially parsed configuration with a completely deserialized one (using a new instance of XStream).
Related
I'm creating a JavaModule with some utilities class.
This module will used from some different Java Applications (these projects will be have the dependency into their pom files).
Into my JavaModule I would like to use some properties files to store the settings values. I con't use Spring int this module.
What's the best practice to use the properties files into a JavaModule without using Spring annotations?
Is it the correct way as reported in this example?
What's the correct place where I have to put the properties files? Can I use a dedicated folder?
Is there a way to override a specific value that it's contained into my Java Module's properties file from a Java Application that use my module?
I would use that logic, and afaik is the most common. But I was also in a project in which we used ResourceBundle even though it should be used to retrieve locale specific data, because it was less verbose.
In that case was just:
ResourceBundle.getBundle("properties").getString("my.property");
Once again. The example from mkyong would be my first choice for anything but a POC.
I have an application that consists of a grid of hazelcast nodes which uses extensive runtime bytecode generation (asm). Specifically I am dynamically building predicate<> Java functions from user entered filter expressions. I would like to store the predicates in a map so that they are available across the cluster without having to be recompiled. Predicates are not the only instance of this. I also have ORM style mapping classes that are generated at runtime which need to be shared across the cluster. These classes are loaded by a custom classloader called DynamiClassLoader.
At first I was unable to store my custom generated classes in Hazelcast IMaps, getting a ClassNotFoundexception. However, I found if tell Hazelcast to use my custom DynamicClassLoader using Config.setClassLoader() then it is able to find my dynamic classes and use them in the local member so I have no issues serializing and deserializing instances of my custom classes in IMaps in the same member.
However, I am still unable to deserialize instances of my predicates which were inserted into the map by a different member. I have enabled UserCodeDeployment and stepped through the code in my debugger to confirm that if it cannot find the class locally then it is hitting UserCodeDeploymentClassLoader.java and on the classNotFoundException it is proceeding to check other members for the classes but it is unable to find them. I haven't been able to discover how exactly this works. it seems to look in an internal map for which member any given class can be found on and it does not find my classes in there. I believe it dispatches an operation to other members then to look for the class, but in this case it looks like my custom classloader isn't used so it's not able to find my custom classes.
How can I make dynamically generated classes work with UserCodeDeployment on Hazelcast? Is there a way I can 'register' my dynamic classes with the member's code service or something like that?
Thankyou,
Troy.
I've finally figured this out after extensive debugging. It turns out that the operation in Hazelcast on the target member to find a class calls loadBytecodeFromParent() in ClassDataProvider.java. This looks for a .class file using getResourceAsStream on the classloader:
String resource = className.replace('.', '/').concat(".class");
...
is = parent.getResourceAsStream(resource);
Which basically looks for the class file on the filesystem. Since my dynamic classes are entirely in memory there is no .class file resource for it to find.
I resolved this, by putting a hashmap in my DynamicClassLoader to keep the generated bytecode in and overriding getResourceAsStream to return that bytecode when it's available before looking further. Now it works!
I can access Java class and methods when executing xquery with Saxon when they are declared correctly (through namespace pointing to package and class) but I wonder if there is a way to create a kind of "dynamic" class path at each run to load external jar file and search classes in it instead of in the current project/program classpath (as I cannot add all possible class in it).
So for instance I have something like :
declare namespace dpr="java:com.*****.atm.dpr.common.util.DPRConfigurationLoader";
declare variable $rules as node()* := doc(dpr:getApplicationProperty('Common','RulesFileLocation'))//category;
I can replace the path the real class with an emulated version but it means I must create each possible class on my side (not really a good way as it means a "patch" for each new java call...).
So if I provide a jar containing the classes I need is there a way to load it so that the namespace point to it ?
I know I can load .class file if they are on classpath, but 3 jar files entirely ?
Thanks.
Technically, Saxon doesn't require external classes to be on the classpath - it requires them to be accessible using the appropriate ClassLoader. If you understand ClassLoaders and are prepared to write your own or configure third-party offerings, then you can load classes from anywhere. All the hooks are there in Saxon if you want to do such things; but there's nothing packaged with the product.
Some of the thing you could try include:
With Configuration.setDynamicLoader() you can change the way Saxon does dynamic loading of external classes, including the classes used for Java extension functions.
With Configuration.getDynamicLoader().setClassLoader() you could provide a different ClassLoader for loading classes, for example a URLClassLoader.
With ProfessionalConfiguration.setExtensionBinder("java", XXX) you could register a customized JavaExtensionLibrary, typically as a subclass of the standard one, allowing you to change the way URIs are mapped to Java classes and the way methods are selected (for example)
This is all very low-level system programming and is not for the faint-hearted.
I'm writing an annotation processor for an Android project and have run into a situation. I would like to process annotated classes from a library module, i.e. app module depends on library module and needs to process annotated classes from the library module.
However, the annotation processor isn't able to "see" the annotations from the dependency, presumably because the code is already compiled. See here for an issue on another library. A demonstration of the problem with my project is on the branch here. The annotations from sample module are processed but the ones from the lib module are not.
This is all well and good and I'd resigned myself to living without this feature, but it turns out the Android data-binding library can process annotations from modules and even third party libraries. This library, for example, provides #BindingAdapter methods that are processed fine by the app.
I played around with setting retention types on the annotations I use to no avail. The only significant difference I can see is that the data-binding processors target methods while my methods target classes (types), but I don't think that should make a difference from the processor. So I'm thinking it might have something to do with the data-binding processor being part of the Android plugin but I'm not sure how that helps here.
Anyone know how this is done?
Android Data Binding can't process annotations on dependencies, either. Instead, it processes the libraries at the compile time of the library and saves the information to an intermediate file as part of its archive (e.g. jar file). It then loads that intermediate file information from the dependency instead of reading the annotations.
If you save the intermediate information as a resource of the jar file dependency, you can pull it from the jar file pretty easily. If I recall correctly, it should be in your class path and you can use the ClassLoader's getResource() method. My memory may be a little stale on this as it doesn't use the jar file to store the intermediate file information any more.
I have five WSDL's that share namespaces, but not all of them. I generate client code out of them (databinding with XMLBeans). Seperately they compile fine. I create JAR files out of each generated client code.
Once I try to use all JAR files within a project, I get naming / compile conflicts.
I want to reuse as much as possible. Is there any smart way to deal with this (rather than giving each client an own node in the package structure)?
The XMLBeans (2.x) faq notes the limitations of xsdconfig namespace mapping:
Note: XMLBeans doesn’t support using two or more sets of java classes (in different packages) mapped to schema types/elements that have the same names and target namespaces, using all in the same class loader. Depending on the direction you are using for the java classes to schema types mapping, some features might not work correctly. This is because even though the package names for the java classes are different, the schema location for the schema metadata (.xsb files) is the same and contains the corresponding implementing java class, so the JVM will always pick up the first on the classpath. This can be avoided if multiple class loaders are used.