Accessing properties in Karaf cfg file from java? - osgi

I am using cm:property-placeholder in blueprint to load config file:
<!-- External configuration -->
<cm:property-placeholder persistent-id="mubyndle" update-strategy="reload">
<cm:default-properties>
<cm:property name="schemaValidation" value="false"/>
</cm:default-properties>
</cm:property-placeholder>
<bean id="myBean" class="com.mybean">
<property name="abc" value="${abc}" />
</bean>
I can set values into beans, like ${abc}.
How can I access any other property of the config from java?
I am planning to add list of properties:
prop1=11
prop2=22
...
propn=nn
I cannot add all in blueprint as the number varies.
Thank you,
Viktor

Add reference to ConfigurationAdmin service in blueprint:
<reference id="configAdmin" interface="org.osgi.service.cm.ConfigurationAdmin" />
Set it to bean:
<bean id="myBean" class="com.mybean">
<property name="abc" value="${abc}" />
<property name="configAdmin" ref="configAdmin" />
</bean>
In bean:
private ConfigurationAdmin configAdmin;
public void setConfigAdmin(ConfigurationAdmin configAdmin) throws IOException {
this.configAdmin = configAdmin;
System.out.println(configAdmin);
System.out.println(configAdmin.getConfiguration("any-persistent-id").getProperties());
}

You can set org.apache.aries.blueprint.compendium.cm.CmPropertyPlaceholder into myBean as <property name="cmpp" ref="cmpp" /> after giving it id <cm:property-placeholder id="cmpp" ....
Then add setter in myBean for cmpp:
public void setProperties(CmPropertyPlaceholder properties) {
Configuration config = CmUtils.getConfiguration(properties.getConfigAdmin(), properties.getPersistentId());
if (config != null) {
Dictionary props = config.getProperties();
System.out.println(props);
}
The only problem is bundle org.apache.aries.blueprint.cm does not export package org.apache.aries.blueprint.compendium.cm, so I can't access CmPropertyPlaceholder in java. Is there any command in karaf that would additionally export a package of a bundle?
It is possible to access configuration through context, will look into that and post.

You better do this:
a) in blueprint.xml
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.1.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
...
<cm:property-placeholder persistent-id="<name of cfg file>"
update-strategy="reload">
<cm:default-properties>
<cm:property name="<property name in file>" value="<value>" />
</cm:default-properties>
</cm:property-placeholder>
<bean id="<name of Bean>" class="<full name of class>" >
<property name="<property name in file>" value="${<value>}"></property>
</bean>
b) inside "bean"
define a public constructor (definition required by Spring)
define a variable and its Setter:
private <Type of> <name of variable>;
public <Constructor> (){} // no parameters
public void set<property name in file first upper letter>(<Type of> <property name in file>) {
<name of variable> = <property name A>;
}
c) add into '/etc' folder the configuration file:
<name of cfg file>.cfg
Obviously, within it, the property:
<Property name> = <value>

Related

How to include properties from external file to hibernate.cfg.xml using spring in a standalone app(jar)

I need to be able to store database config properties in an external file that well be used by the application jar and include it in form of jstl expressions. (like : ${password} etc.)?
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="connection.url">jdbc:db2://localhost:50001/svntools</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.ibm.db2.jcc.DB2Driver</property>
-->
<property name="show_sql">true</property>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.BrancheEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.RevisionEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.ProjectEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.StatistiqueEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.DomaineEntity"/>
</session-factory>
</hibernate-configuration>
SpringConfig.xml file
<?xml version="1.0" encoding="UTF-8"?>
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="projectDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.ProjectDAOImpl">
</bean>
<bean id="reportDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.ReportDAOImpl" />
<bean id="brancheDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.BrancheDAOImpl" />
<bean id="domaineDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.DomaineDAOImpl" />
<bean id="svnKitDa"
class="fr.gouv.education.sirhen.svnreporting.domaine.DA.impl.SVNKitDAImpl" />
<bean id="RevisionServicesBean"
class="fr.gouv.education.sirhen.svnreporting.domaine.impl.RevisionsServicesImpl">
<property name="svnKitDa" ref="svnKitDa" />
<property name="brancheDAO" ref="brancheDAO" />
</bean>
<bean id="parser" class="fr.gouv.education.sirhen.svnreporting.transvers.utils.ParserImpl" />
<bean id="reportServices"
class="fr.gouv.education.sirhen.svnreporting.service.impl.ReportServicesImpl">
<property name="reportDAO" ref="reportDAO" />
<property name="brancheDAO" ref="brancheDAO" />
<property name="projectDAO" ref="projectDAO" />
<property name="parser" ref="parser" />
</bean>
<bean id="projectServices"
class="fr.gouv.education.sirhen.svnreporting.service.impl.ProjectServicesImpl">
<property name="projectDAO" ref="projectDAO" />
</bean>
<bean id="domaineServices"
class="fr.gouv.education.sirhen.svnreporting.service.impl.DomaineServicesImpl">
<property name="domaineDAO" ref="domaineDAO" />
</bean>
<bean id="generator"
class="fr.gouv.education.sirhen.svnreporting.domaine.generatorDocServices.impl.GeneratorDocServiceImpl" />
The class that use the session:
package fr.gouv.education.sirhen.svnreporting.persistance.impl;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import fr.gouv.education.sirhen.svnreporting.persistance.ProjectDAO;
import fr.gouv.education.sirhen.svnreporting.persistance.eo.ProjectEntity;
public class ProjectDAOImpl implements ProjectDAO {
private static final String Location_Hibernate =
"resources/hibernate.cfg.xml";
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void addProject(ProjectEntity project) {
File hibernatePropsFile = new File(Location_Hibernate);
Session session=new Configuration().configure(hibernatePropsFile).buildSessionFactory().openSession();
Transaction t=session.beginTransaction();
session.saveOrUpdate(project);
t.commit();
session.close();
}
public List<ProjectEntity> getProjects() {
File hibernatePropsFile = new File(Location_Hibernate);
Session session=new Configuration().configure(hibernatePropsFile).buildSessionFactory().openSession();
Transaction t=session.beginTransaction();
List<ProjectEntity> projects= session.createCriteria(ProjectEntity.class).list();
t.commit();
session.close();
return projects;
}
public List<String> getProjectsNames() {
File hibernatePropsFile = new File(Location_Hibernate);
Session session=new Configuration().configure(hibernatePropsFile).buildSessionFactory().openSession();
Transaction t=session.beginTransaction();
List<ProjectEntity> projects= session.createCriteria(ProjectEntity.class).list();
t.commit();
session.close();
List<String> ProjectsNames=new LinkedList<String>();
for( ProjectEntity projet : projects)
{
ProjectsNames.add(projet.getName());
}
return ProjectsNames;
}
}
An alternate approach is you can directly use hibernate.properties file instead of hibernate.cfg.xml.
But if you want to use another file then hibernate.properties file then please refer link given below:
How to read database configuration parameter using properties file in hibernate
Still, if you want to read properties file separate then you can read with normal java code to read properties file from class path or relative file path and set those properties on environment using ConfigurableEnvironment of spring.
Edited Answer
If you want to read properties file outside of your application (jar) then you can read properties file programmatically from relative file path.
I have provided one answer earlier and that was the same situation for read properties file, You can follow my Edited answer from there.
Spring Boot embedded Tomcat not loading external properties file in ApplicationListener
Now You can use System properties or Environment properties to store properties loaded earlier from relative file path and then it will available any where in the application.
#Autowired
private ConfigurableEnvironment myEnv;
or
System.setProperty ("propertyName", "propertyValue");

Spring configuration split between xml resource and Java configuration

I am trying to mix both xml and Java Configuration.
I have a spring-security.xml resource that I import in my application boot.
Say this was a part of the initial xml:
<bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="${ldap.url}" />
<property name="base" value="${ldap.base}" />
<property name="userDn" value="${ldap.user}" />
<property name="password" value="${ldap.password}" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="ldapContextSource" />
</bean>
Can I move just this part to be a Java config ? Or would the references be an issue.
Thank You
You can move it to Java Config
Declare configuration class
#Configuration
public class AppConfig {
#Bean
public LdapContextSource ldapContextSource(){
LdapContextSource lcontext = new LdapContextSource();
lcontext.setUrl("${ldap.url}");
lcontext.setBase("${ldap.base}");
lcontext.setUserDn("${ldap.user}");
lcontext.setPassword("${ldap.password}");
return lcontext;
}
#Bean
public LdapTemplate LdapTemplate(){
LdapTemplate lTemplate = new LdapTemplate(ldapContextSource());
return lTemplate;
}
}
In your XML add
<context:annotation-config/>
<bean class="com.mypackage.AppConfig"/>

indexing document to a specific collection using spring data solr

I am trying to index a document to a specific collection in solr. The collection name is 'program'. I am using spring data solr.
I am getting the below error when trying to save the document:
HTTP ERROR 404
Problem accessing /solr/update.
Reason:Not Found
My assumption is that the annotation #SolrDocument is not recognized. spring-data-solr is trying to post the document to /solr/update whereas it should try to post it to /solr/program/update.However I am not sure how to prove it or fix it.
My schema is available on the link below:
http://<solr-host>/solr/program/schema
The update request handler is available in the link below:
http://<solr-host>/solr/program/update
spring-config-xml
<context:annotation-config />
<context:component-scan base-package="com.oostnet.controllers, com.oostnet.models, com.oostnet.services" />
<mvc:annotation-driven />
<solr:solr-server id="solrServer" url="http://<solr-host>/solr" />
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg ref="solrServer" />
</bean>
<solr:repositories base-package="com.oostnet.solr.repositories" />
Model definition:
package com.oostnet.models.documents;
#SolrDocument(solrCoreName="program")
public class Program {
#Id
#Indexed
private String id;
<more variables>
}
Repository definition:
package com.oostnet.solr.repositories;
public interface ProgramRepository extends SolrCrudRepository<Program, String> {
}
Controller:
package com.oostnet.controllers;
public class ProgramController{
private ProgramRepository programRepository;
#Autowired
public void setProgramRepository(ProgramRepository programRepository) {
this.programRepository = programRepository;
}
public void createProgram(Program program) {
programRepository.save(program);
}
}
Below are the versions used:
<spring.data.solr.version>1.3.2.RELEASE</spring.data.solr.version>
<spring.version>4.1.4.RELEASE</spring.version>
solr server version - solr-spec 4.10.2
To work on multiple collection you need to enable multiple repository under spring configuration as below :-
<context:annotation-config />
<context:component-scan base-package="com.test.solr" />
<solr:solr-server id="solrServer" url="http://localhost:8983/solr" />
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg ref="solrServerFactory" />
</bean>
<solr:repositories base-package="com.test.solr.repositories" multicore-support="true" />
<bean id="solrServerFactory"
class="org.springframework.data.solr.server.support.MulticoreSolrServerFactory">
<constructor-arg ref="solrServer" />
<constructor-arg name="cores">
<list>
<value>program</value>
</list>
</constructor-arg>
</bean>

spring bean initializing instances differently via property wiring

I have the following properties in a property file:
context1.property1=value1
context1.property2=value2
context1.property3=value3
context2.property1=value4
context2.property2=value5
context2.property3=value6
I have a bean with the following structure:
class Bean {
private property1;
private property2;
private property3;
}
Is there any way better to initialize 2 instances of Bean without writing something like:
<bean id="bean1" class="com.test.Bean">
<property name="property1" value="${context1.value1}" />
<property name="property2" value="${context1.value2}" />
<property name="property3" value="${context1.value3}" />
</bean>
<bean id="bean2" class="com.test.Bean">
<property name="property1" value="${context2.value1}" />
<property name="property2" value="${context2.value2}" />
<property name="property3" value="${context2.value3}" />
</bean>
Thanks!
Have a look at PropertyOverrideConfigurer:
Property resource configurer that overrides bean property values in an application context definition. It pushes values from a properties file into bean definitions.
Configuration lines are expected to be of the following form:
beanName.property=value
Example properties file:
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb
See also
Using PropertyOverrideConfigurer with Annotated Classes in Spring 3

MessageSource and PropertyPlaceholderConfigurer cannot load messages but with classpath*

My applicationContext.xml is in path:
src/main/resources/META-INF/spring
and property files are in path:
src/main/resources/messages
and I load spring context in web.xml as follows:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/spring/applicationContext.xml</param-value>
</context-param>
when I am configuring MessageSource and PropertyPlaceholderConfigurer as follows:
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:messages/apps.properties</value>
</list>
</property>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:messages/ValidationMessages</value>
<value>classpath:messages/app</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
they both don't work, it only works when I change classpath to classpath*
Any ideas why?
From Spring documentation:
4.7.2.2 The classpath*: prefix
[...] location string may use the special classpath*: prefix: [...]
This special prefix specifies that all classpath resources that match the given name must be obtained [...], and then merged to form the final application context definition.
Are you sure there are no other messages/apps.properties files on your CLASSPATH coincidentally taking precedence and overriding your file? This description suggests that you might have several same named files that are merged when * is used.
Can you check this by calling:
SomeClass.class.getClassLoader().getResources("/messages/apps.properties");
?
Look at this excellent article for classpath v classpth* difference in regards to spring resource loading, I did some testing on your problem in my testing it worked whether i used classpath or classpath*
I am listing the code here about the test i did
I created a this directory structure (META-INF/spring under src/main/resource) placed context.xml
I am listing complete context.xml here
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:messages/apps.properties</value>
</list>
</property>
</bean>
<bean class="prasanna.service.TestBean">
<property name="appName" value="${appname}"></property>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:messages/ValidationMessages</value>
<value>classpath:messages/apps</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
</beans>
Listing for apps.properties
appname=spring mvc app
Listing for ValidationMessages.properties
error.name=Invalid name
TestBean is rather simple
public class TestBean
{
private String appName;
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
}
I am using a simple java class to load the property files and read them
public class LoadContext
{
public static void main(String[] args)
{
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:META-INF/spring/context.xml"});
ReloadableResourceBundleMessageSource msgs = ctx.getBean(ReloadableResourceBundleMessageSource.class);
TestBean testBean = ctx.getBean(TestBean.class);
Assert.assertTrue(testBean.getAppName().equals("spring mvc app"));
String msg = msgs.getMessage("appname", new Object[]{new DefaultMessageSourceResolvable("appname")}, null);
System.out.println(" "+ msg);
String msg2 = msgs.getMessage("error.name", new Object[]{new DefaultMessageSourceResolvable("error.name")}, null);
System.out.println(" "+ msg2);
}
}

Resources