using json files for properties with apache commons configuration2 - java

I am trying to enable usage of JSON for configuration properties.
Upgraded to Commons Configuration2 (2.8) hoping that this will work out-of-the box.
I am initializing like this:
new CombinedConfigurationBuilder()
.configure(new Parameters()
.fileBased()
.setFileName(CONFIGURATION_SOURCES)
.setEncoding(UTF_8.toString()))
.getConfiguration();
This is my CONFIGURATION_SOURCES file:
<configuration>
<properties fileName="this-works.properties" />
<properties fileName="this-does-not-work.json" />
</configuration>
My JSON properties file (which does not get loaded):
{
"foo": "bar"
}
When testing it with
#Test
public void shouldLoadPropertiesFromJson() {
assertThat(configuration.getString("foo"), is("bar"));
}
fails because foo is null instead of bar :(
Any suggestion(s)?

Related

How to use shared library in websphere liberty profile

It seems simple but ...
I'm just starting to learn liberty profile.
I can't use shared library.
here's documentation:
https://www.ibm.com/support/knowledgecenter/SSD28V_liberty/com.ibm.websphere.wlp.core.doc/ae/cwlp_sharedlibrary.html
so in server.xml I put (and restart server), for example:
<library>
<folder dir="C:/libs/gson/"></folder>
<!-- or even <file name="C:/libs/gson/gson-2.3.1.jar" /> -->
</library>
Anyway at runtime I receive: "java.lang.NoClassDefFoundError: com/google/gson/Gson"
On a servlet I just have the import and a simple use:
...
import com.google.gson.Gson;
...
#WebServlet("/")
public class HelloWorld extends HttpServlet {
...
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Serialization
Gson gson = new Gson();
...
What I'm missing?
Adding a library element to server configuration doesn't automatically make it available to applications. You need to configure the application to have access to the library, for example,
<application location="myapp.war">
<classloader commonLibraryRef="gsonLib"/>
</application>
<library id="gsonLib">
<file name="C:/libs/gson/gson-2.3.1.jar" />
</library>
The part you are missing is that the application needs to be configured to reference the library. There are a few ways to do this:
Use the Global shared library as described here: https://www.ibm.com/support/knowledgecenter/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_classloader_global_libs.html
Then, simply change your library ID to global like this:
<library id="global">
Give your library an ID and add a <classloader commonLibraryRef="..."/> as described in #njr's answer

Setting per application properties on Wildfly

I am normally the Tomcat guy but we use Widlfly on one of our client project.
With Tomcat, I can set "per application" properties by creating a separate context for each application, just as Tomcat documentation very nicely says.
This way, my WebApp1.war can run with my.property.value=Cat and WebApp2.war can run with my.property.value=Dog at the same time.
I haven't found any similar documentation / feature with Wildfly. Could you please advice me how to set properties to applications individually, or point me to the documentation?
Thank you. :-)
In Wildfly, you can create modules holding properties:
Under the ${JBOSS_HOME}/modules, add a directory like my/group/app1/conf/main.
Under the ${JBOSS_HOME}/modules/my/group/app1/conf/main, create the file module.xml with content:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="my.group.app1.conf">
<resources>
<resource-root path="." />
<!-- Insert resources here -->
</resources>
</module>
Copy your *.properties file(s) under the ${JBOSS_HOME}/modules/my/group/app1/conf/main
Add as dependency <module name="my.group.app1.conf" export="true" /> in the jboss-deployment-structure.xml of the WebApp1.war
In a Spring XML, assuming you have in the configuration module a file named my-app.properties the properties can be loaded into the context with:
<context:property-placeholder
location="classpath*:*my-app.properties"
local-override="false"
ignore-unresolvable="false"/>
To have a configuration module for the WebApp2.war, just repeat the steps above but the new module must have its own unique name.
I think, I found a workaround for this problem. A asume, that app1.war and app2.war are different wars and not the same with different names.
Then you can use the Application initialization process at runtime to define per application a different spring.config.name. Instead of application.properties then every WAR (and of corse every jar) looks for a application specific called properties file.
/** Main Entry Point for this Application */
#SpringBootApplication(scanBasePackages = "de.mach.selfservices")
public class Application extends SpringBootServletInitializer implements WebApplicationInitializer {
// JAR init
public static void main(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
if (!System.getProperties().containsKey("spring.config.name")) {
builder = builder.properties("spring.config.name:app1");
}
builder.run(args);
}
// WAR init
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
if (!System.getProperties().containsKey("spring.config.name")) {
builder = builder.properties("spring.config.name:app1");
}
return builder.sources(Application.class);
}
}
The second application has then app2 in spring.config.name. In both cases the default behaviour of SpringBoot is like expected. It looks inside and outside the WAR/JAR for app1.properties or app2.properties. So you can put two files in wildfly/standalone/configuration and can configure both WARs independently.
For me the following approach worked.
First i changed name of application properties.
Second i changed the path to configuration file using Wildfly configuration path.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
String configPath = System.getProperties().getProperty("jboss.server.config.dir") + "/";
return builder
.properties("spring.config.name:my-app")
.properties("spring.config.location:" + configPath)
.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

OSGI DS: properties -> ParseException

I use apache felix and I have the following annotation for my DS
#Component(immediate = false,properties = {"name:String=stub"})
Maven generates the following xml
<component ...>
<implementation ..../>
<service>
....
</service>
<properties enty="name:String=stub"/>
</component>
However, when I start this bundle I get the following:
ERROR: com.temp.biz (55): General problem with descriptor entry '/OSGI-INF/com.temp.MyClass.xml'
org.apache.felix.scr.impl.parser.ParseException: Exception during parsing
at org.apache.felix.scr.impl.metadata.XmlHandler.startElement(XmlHandler.java:364)
at org.apache.felix.scr.impl.parser.KXml2SAXParser.parseXML(KXml2SAXParser.java:82)
at org.apache.felix.scr.impl.BundleComponentActivator.loadDescriptor(BundleComponentActivator.java:245)
at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:158)
at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:479)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:414)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:443)
at org.apache.felix.framework.util.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:913)
How to fix it? The problem disappears as soos as I remove properties from #Component.
For the OSGi DS #Component annotation, you want to use property:
#Component(immediate = false, property = {"name:String=stub"})
For the Felix SCR annotations, refer to the documentation.

How to load external properties file through OSGi blueprint property-placeholder and Java DSL

I have a bundle installed in Apache servicemix that is using apache blueprint for configuration. I am using an external properties file abc.cfg located in /config folder and is being loaded as follows:
via blueprint
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel-cxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/blueprint/core"
xsi:schemaLocation="
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0">
<cm:property-placeholder id="myProperties" persistent-id="abc" />
via java DSL
public class MyActivator implements BundleActivator {
#Override
public void start(final BundleContext context) throws Exception {
final ServiceReference serviceReference = context.getServiceReference(ConfigurationAdmin.class.getName());
if (serviceReference != null) {
final ConfigurationAdmin admin = (ConfigurationAdmin) context.getService(serviceReference);
final Configuration configuration = admin.getConfiguration("abc");
final Dictionary<String, Object> configurations = configuration.getProperties();
if (configurations == null) {
throw new CustomException("Exception in loading properties file");
}
populateProperties(configurations);
}
}
}
Everything works fine but now i need to move the property file in custom location to segregate property files from different bundles. So i moved abc.cfg in /config/myFolder/ but i am unable to specify the new location to my bundle in either ways. I tried using ext:property-placeholder but it didn't work, probably because i am using it wrong(couldn't find anything comprehensive to understand it).
So please guide me on how can i specify location for my properties file in cm:property-placeholder and through configuration admin service in java DSL. Also, i am not sure if it is ok to load the same properties file in two different ways in my bundle.
Neither the blueprint cm:property-placeholde nor the configuration-admin service use the file you added to the etc folder. The cm is just another way of using the configuration admin service.
The felix FileInstaller does read cfg files from the etc folder of your ServiceMix instance and does propagate those properties to the Configuration Admin service.
So in your case you'll need to add another configuration to the FileInstaller to read from another path.
This can be done by adding a new configuration file:
org.apache.felix.fileinstall-mySpecialDir.cfg
where you add the new folder to be watched:
felix.fileinstall.dir = myNewSpecialDirectory-to-be-watched
plus some more if needed.
Documentation for it can be found here

CodeSource on Liberty Profile 8.5.5.5

I'm trying to deploy a dropwizard (dw) application using wizard-in-a-box (wiab) on IBM Liberty Profile 8.5.5.5, but I'm encountering som issues with the io.dropwizard.util.JarLocation class. wiab will try to get the location of the Listener class wrapping the dw application but fails to do so since the CodeSource object in the class' ProtectionDomain is null.
klass.getProtectionDomain().getCodeSource().getLocation()
However, I've tried to deploy on Tomcat 8 and the latest Liberty Profile v9 beta, and they both work fine.
Both server.xml files on the Liberty servers look exaktly the same in terms of features.
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>servlet-3.1</feature>
<feature>jsp-2.3</feature>
<feature>el-3.0</feature>
<feature>websocket-1.1</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443" />
<applicationMonitor updateTrigger="mbean" />
<application id="moshpit_war_war_exploded" location="D:\code\moshpit\moshpit-war\target\moshpit" name="moshpit_war_war_exploded" type="war" context-root="/" />
</server>
I've tried deploying both the ordinary war and the exploded war from inside IntelliJ, as well as using the dropin folder with a pre-built war. The v9 beta version will play nice, but not 8.5.5.5.
This is the Listener class wrapping the dw app:
#WebListener
public class MoshpitWebApplication extends WebApplication<MoshpitConfiguration> {
private static final Logger LOGGER = LoggerFactory.getLogger(MoshpitWebApplication.class);
public MoshpitWebApplication() {
super(new MoshpitApplication(), "/configuration/moshpit.yml");
}
}
and this is my dw Application class
public class MoshpitApplication extends Application<MoshpitConfiguration> {
public MoshpitApplication() {
}
public static void main(String[] args) throws Exception {
new MoshpitApplication().run(args);
}
#Override
public String getName() {
return "moshpit";
}
#Override
public void initialize(Bootstrap<MoshpitConfiguration> bootstrap) {
bootstrap.setConfigurationSourceProvider(new FileConfigurationSourceProvider());
// nothing to do yet
}
#Override
public void run(MoshpitConfiguration configuration, Environment environment) throws Exception {
final Template template = configuration.buildTemplate();
environment.healthChecks().register("template", new TemplateHealthCheck(template));
environment.jersey().register(new HelloWorldResource(template));
}
}
Update:
This seems to be a general problem with Liberty 8.5.5.5. Tried deploying a completely different application and I observed the same behaviour. The CodeSource is null for application classes.
The Liberty profile doesn't currently set the CodeSource for application classes. As you note this is addressed in the current beta and will be addressed when 8.5.5.6 is released on June 26th.

Categories