HOCON: multiple reference.conf resolution issue - hocon

I have multi-module project under SBT.
Project A (library) has reference.conf file with A's configuration parameters. Project A depends on akka-actor library, which ships with its own reference.conf file. Project A redefines some akka's parameters in own reference.conf.
Project B depends on A.
When I call ConfigFactory.load() in B, I'm getting wrong order of reference.confs merging. It first takes A's config, then applies akka-actor's config over it. Eventually, I'm getting initial akka-actor's configuration.
How can I fix it? I need to get akka-actor's config loaded first, then my A's config should be applied over it.

Ok, looks like I've found the answer in sources of ConfigFactory.
All the reference.conf is being loaded through ClassLoader.getResources. It returns java.util.Enumeration[URL]. The order of URLs in this enum is the answer to the question. So all you need to do: ensure the order of your reference.conf resources in this enumeration properly arranged.
Here is an example of how to do that. First, create your own version of ClassLoader by overriding getResources method:
import scala.collection.JavaConverters._
class CustomClassLoader(loader: ClassLoader) extends ClassLoader(loader){
override def getResources(name: String): util.Enumeration[URL] = {
val resources = super.getResources(name).asScala.toList
// arrange resources as you wish here
java.util.Collections.enumeration(resources.asJava)
}
}
Last, call load method of ConfigFactory with your CustomClassLoader instance.

Related

What does create method do in gradlePlugin.plugins?

In the gradle doc: https://docs.gradle.org/current/userguide/custom_plugins.html#sec:custom_plugins_standalone_project
The code block is:
gradlePlugin {
plugins {
create("simplePlugin") {
id = "org.example.greeting"
implementationClass = "org.example.GreetingPlugin"
}
}
}
I noticed it calls create method. And I looked the source code. It says:
Creates a new item with the given name, adding it to this container,
then configuring it with the given action.
What does it mean? Is it actually used anywhere? Or it can be any name does not really matter?
gradlePlugin.plugins is a NamedDomainObjectContainer - which are used by Gradle to hold multiple objects, each with a name.
The documentation on plugin development goes into more detail on the usage of NamedDomainObjectContainers.
Sometimes you might want to expose a way for users to define multiple, named data objects of the same type.
[...]
It’s very common for a plugin to post-process the captured values within the plugin implementation e.g. to configure tasks.
Since the elements of a NamedDomainObjectContainer can be any type, there's no specific usage for one. Generally they are used to configure the Gradle project, for example creating specific tasks, configuring source code locations.

XMLSchema namespace is ignored (JAXB unmarshal fails)

I'm trying to unmarshal a complex payload for which I do not have a complete definition (just the wrapper, which then defines the actual varying content as
#XmlAnyElement(lax = true)
protected Object any;
Now, I've done this before in another project and it worked just fine, in a two step unmarshal - first do the wrapper, then access any as a Node and unmarshal that to the expected content (for which I had no xsd and I had to manually model into classes)
This time however, the content comes back namespaced and the only way I've gotten it to work is to add namespace to every XmlRootElement, XmlElementand XmlType in all of my own modeled structures. Obviously this is a huge pain and I tried to add an XmlSchema to the package that holds the domain objects mapping the Xml payload, but for some reason that is not picked up by the unmarshaller.
#javax.xml.bind.annotation.XmlSchema(namespace = "http://mynamespace.com",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.myproject.schema;
I've tried creating unmarshallers in multiple ways, none pick-up the XmlSchema in the package
val marshaller = Jaxb2Marshaller()
marshaller.setPackagesToScan("supplier.package", "com.myproject.schema")
or
val unmarshaller = JAXBContext.newInstance(myKClass.java).createUnmarshaller()
My (relevant) dependecies look like this
implementation("org.springframework.boot:spring-boot-starter-webflux:2.4.1")
implementation("org.springframework.ws:spring-ws-core:3.0.10.RELEASE")
implementation("javax.xml.bind:jaxb-api:2.3.1")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.10.1")
EDIT:
So apparently the package-level annotation is not read because the package-info.java file seems to be excluded from the build (and so it's not picked up by the classloader). I've looked at the classes build from the xjc output and those do contain the package-info.
I'm still looking into why this is happening, maybe there's a flag for Gradle or the Kotlin plugin I can switch to get that included.
Problem is fixed indeed by a package-level XmlSchema annotation. However, one must check that it is indeed picked-up when the class is loaded (reflection is your friend) and if not, keep in mind that package-info.java files must be put in your Java sources and not your Kotlin sources (seems obvious, but it's not always as obvious when you're a few hours down the rabbit hole).

How to reference a module property in tibco-bw6 from XPath

I'm trying to reference a module property from tibco business works 6.
Do you guys have an example about the getModuleProperty("")?
What kind of input should I use?
Should I use the entire path or just the name of the property?
You need to first add a process property to your process (it's under properties if you click outside of the main process area). In there you can reference a module property. You can then use the process property in XPath.
First off, you need to include a few dependencies in your project. (Documented here)
Then write some code access the properties
#ModuleProperties
public void loadProperties(HashMap<String, String> moduleProperties){
this.myClassProperty = moduleProperties.get("/DB/Property"); // Case Sensitive Path
System.out.println("Completed loading module properties.");
}
You have to use the entire path of the property. you can get it from the META-INF/default.substvar file.

For a Maven project to access its own resources

I have two projects:
A project
B project (lists A as one of B's dependencies)
A has a method that relies on A's resource
When B calls A's method, A ends up access B's resource folder and thus is unable to find A's own resource files.
Any way around this?
In order to ensure that a project will always access its own resources, you need to load them using the Class#getResource method.
Example:
public class MyCalledClass{
public static void loadResource() {
new File(MyCalledClass.class.getResource("file.txt").getPath()); // Will retrieve the file called "file.txt"
// in the project where this class is
new File("file.txt"); // Will retrieve the file called "file.txt" in the project calling this method
}
}

How to package a Gradle plugin?

I'm having trouble figuring out what META-INF/gradle-plugins/plugin.properties has to match. There are two issues here. One is the name of the properties file and one is the value therein set to implementation-class. So here is my question as succinctly as I can put it.
If I have:
META-INF/gradle-plugins/com.my.plugin.properties
What portion of the source plugin does the file name map to? What are the implications of this name? It's source and destination? Am I doing the name correctly or should it not be so qualified?
If inside the file I have:
implementation-class=build.WeirdoPlugin
What are the source and destination of this name?
implementation-class should point to the your main plugin class that implementsPlugin<>
for example, in jmeter-gradle-plugin/src/main/resources/META-INF/gradle-plugins/net.foragerr.FooPlugin.properties
implementation-class=net.foragerr.soanswers.FooPluginImpl
I will then implement a class:
package net.foragerr.soanswers
class FooPluginImpl implements Plugin<Project>{
...
}
To use the plugin, you apply it as (in the new gradle format):
plugins {
id "net.foragerr.FooPlugin" version "xxx"
}

Resources