Share a Property between two blueprints - spring

I am trying to define a property in blueprint 1 and use it as the default property in blueprint 2.
Both blueprints will be loaded into the same Karaf OSGI container but exist in different bundles. The manifests are already set up with necessary dependency info.
Here is my Blueprint1 that defines the property i want to use again in another blueprint:
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<!-- Properties for this blueprint -->
<osgix:cm-properties id="sharedProperties" persistent-id="com.foo.project" update-strategy="reload"
xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
<default-properties>
<property name="shared-property" value="value"/>
</default-properties>
</osgix:cm-properties>
<bean id="myBean"
class="com.foo.MyClass">
<property name="setting" value="{{shared-property}}"/>
</bean>
And my other Blueprint which is trying to use "my-property" defined above:
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<!-- Load the properties from Blueprint1. Intent is to use property defined over there, here. -->
<osgix:cm-properties id="sharedProperties" persistent-id="com.foo.project"/>
<!-- Make properties defined in sharedProperties available using ${} syntax-->
<ctx:property-placeholder properties-ref="sharedProperties" />
<!-- Properties for this blueprint -->
<property-placeholder persistent-id="com.foo.project.blueprint2" update-strategy="reload"
xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
placeholder-prefix="{{{"
placeholder-suffix="}}}">
<default-properties>
<property name="my-property" value="${shared-property}"/>
</default-properties>
</property-placeholder>
<bean id="myBean"
class="com.foo.MyClass">
<property name="setting" value="{{{my-property}}}"/>
</bean>
Ive got a feeling(maybe just hope) this is close to correct but off by a little. If it is correct my issue may be with a missing namespace handler.

By using the "default-properties" tag you are redefining the value. Remove the from the second project. Also, I recommend removing default-properties from both and utilize an externalized cfg file so you do not have a race condition at start-up.
Remove this:
<default-properties>
<property name="my-property" value="${shared-property}"/>
</default-properties>

Related

How to use properties from OSGI/Karaf ConfigurationAdminService with Spring dependency injection

I am trying to inject properties stored in Karaf into my Camel/Spring-Service. So far i tried to inject the properties the way documented in Fuse documentation and Spring.
But both seem outdated: the osgix:cm-properties can't be parsed by current Spring version (Fuse 6.3 uses 3.2.16).
On the other hand Apache Aries seem to have something that could be used now. The aries-blueprint-spring feature contains two bundles:
aries.blueprint.spring
aries.blueprint.spring.extender
I found an old user-list post that points to this bundles. But i can't find any documentation or example using this. We only need to inject the properties.
Have been using OSGi Service Compendium for sometime now and below is some extract from one of my projects, hope it helps.
Important is the declaration of compendium namespace and it's prefix osgix
Also note the declaration of persistent-id as the same has to be defined in Karaf configuration file to be created inside etc directory of your container instance.
Now there is Spring property-placeholder referring to osgix properties declaration and propertyPlaceholder inside CamelContext. Both are required if you want to access properties outside - ${propName} and inside - {{propName}} CamelContext.
To access properties outside Camel Context syntax is ${propertyName}
To access properties inside Camel Context syntnax is {{propertyName}}
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium" xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- A. Configuration Management -->
<osgix:cm-properties id="cachingServicesProp" persistent-id="com.fsafrica.cachingservices.cm">
<prop key="amqBrokerUrl">tcp://localhost:61616</prop>
<prop key="amqUsername">admin</prop>
<prop key="amqPassword">admin</prop>
<prop key="queueName">jms/SRK_CACHE_QUEUE</prop>
</osgix:cm-properties>
<!-- Required for resolving properties for Beans outside CamelContext -->
<ctx:property-placeholder properties-ref="cachingServicesProp" />
<!-- B. ActiveMQ -->
<bean class="org.apache.activemq.camel.component.ActiveMQComponent" id="activemq">
<property name="brokerURL" value="${amqBrokerUrl}" />
<property name="userName" value="${amqUsername}" />
<property name="password" value="${amqPassword}" />
</bean>
<camelContext id="CC-CachingMain" xmlns="http://camel.apache.org/schema/spring">
<!-- Required for resolving properties inside CamelContext -->
<propertyPlaceholder id="properties" location="ref:cachingServicesProp"/>
<!-- JMS INTERFACE -->
<route id="Route-JMSMasterData">
<from uri="activemq:queue:{{queueName}}?transacted=false" />
<log message="#### After putting some data in the Queue (jms/SRK_CACHE_QUEUE) you should be able read this text on Karaf console" />
</route>
</camelContext>
</beans>

Spring Beans getting initialised twice for Entity Manager

I am having a bean defined as below
<bean id="batchManagementService" class="com.amdocs.dc.sprint.batch.service.BatchManagementServiceImpl" autowire-candidate="false">
<property name="repository" ref="batchPersistenceRepository" />
<property name="timeService" ref="batchTimeService" />
<property name="validator" ref="batchValidator" />
</bean>
I am refering this bean in two places in different modules.
However it is getting initialised with two differnt values.
with the JDK proxy which performs correct DB transactions
with the implementor class directly "BatchManagementServiceImpl" as mentioned above.
IN the second case the Entity manager is returning null causing all DB transactions to fail.
The implementor class contains transactional methods.
Any help on this will be appreciated..
Not quite clear from the description for me, but it sounds like your applicationContext is misconfigured within the modules.
Maybe you try an approach like:
MODULE_A:
-applicationContextA.xml
MODULE_B (which should use MODULE_A's beans )
-applicationContextB.xml
MODULE_C (which should use MODULE_B and MODULE_A )
-applicationContextC.xml
The WRONG approach is:
applicationContextA.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
...
<bean id="batchManagementService"...>
applicationContextB.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
<import resource="applicationContextA.xml"/>
<bean id=anotherBean...
applicationContextC.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
<import resource="applicationContextB.xml"/>
<bean id=anotherBean...
In this case, when applicationContextC is created, batchManagementService will be instantiated twice.
Try this one:
applicationContextA.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
...
<bean id="batchManagementService"...>
applicationContextB.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
<!--No import here! -->
<!--<import resource="applicationContextA.xml"/>-->
<bean id=anotherBean...
applicationContextC.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
<!-- No import here -->
<!--<import resource="applicationContextB.xml"/>-->
<bean id=anotherBean...
applicationContextFull.xml
<beans xmlns="http://www.springframework.org/schema/beans">
<import resource="applicationContextA.xml"/>
<import resource="applicationContextB.xml"/>
<import resource="applicationContextC.xml"/>
</beans>
, and try to boot application context using applicationContextFull.xml.
Hope this helps.

Spring systemProperties not appending value properly

I am using Spring 3.1 to create a bean in an web application like below wherein the server contains -DCONFIG_MODE=dev. However, it seems spring is only resolving the filename to configuration.dev without appending the remaining .xml. Could you please point what could be wrong in this.
<?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:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet.xsd">
<bean id="xmlConfig" class="org.quwic.itms.mq.XmlConfiguration" init-method="init">
<constructor-arg type="java.net.URL" value="classpath:configuration.#{systemProperties.CONFIG_MODE}.xml"/>
<constructor-arg type="org.apache.commons.configuration.reloading.ReloadingStrategy" ref="reloadingStrategy"/>
</bean>
<!-- The managed reloading strategy for the configuration bean -->
<bean id="reloadingStrategy" class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy">
<property name="refreshDelay" value="300000"/>
</bean>
</beans>
Thanks,
Fixed it. I wrongly specified the system property as "-DCONFIG_MODE=local -Dprogram.name=JBossTools: JBoss 5.0 Runtime" rather than -DCONFIG_MODE=local "-Dprogram.name=JBossTools: JBoss 5.0 Runtime"

Spring config custom namespace

I have a standalone spring application with an embedded Apache FTP server. The config looks like this -
<?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:afs="http://mina.apache.org/ftpserver/spring/v1"
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
http://mina.apache.org/ftpserver/spring/v1 http://mina.apache.org/ftpserver/ftpserver-1.0.xsd">
<context:property-placeholder location="classpath:config.properties" system-properties-mode="OVERRIDE"/>
<afs:server id="server" anon-enabled="false">
<afs:listeners>
<afs:nio-listener name="default" port="2222"
idle-timeout="60" />
</afs:listeners>
<!-- other AFS config -->
</afs:server>
</beans>
I would like to load the port property of nio-listener from a properties files, but
<afs:nio-listener name="default" port="${ftp.port}"
idle-timeout="60" />
doesn't work, since port is defined in the xsd as xs:int. I'd like to know if there is any workaround (using SpEL?) that will allow me to use the AFS namespace and load the port property from a file or from system properties.
You could try with PropertyOverrideConfigurer.
The problem is that you need to know the bean name that the <afs:server> tag define (may be 'server') and the property type that <afs:listeners> define (may be a managed list of bean definitions).
Look at STS bean explorer to find correct answers and try whith something like
<context:property-override location="classpath:config.properties" />
server.listeners[0].port=2222
Other option is disable schema validation setting validating to false before refresh in the xml application context.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml"}, false);
context.setValidating(false);
context.refresh();
After exploring a few options, I've decided that the easiest way is to step outside the afs namespace for the just the listener configuration. Final config looks like this -
<bean id="listenerFactory" class="org.apache.ftpserver.listener.ListenerFactory">
<property name="port" value="${ftp.port}" />
<property name="dataConnectionConfiguration">
<bean factory-bean="dataConnectionConfigurationFactory"
factory-method="createDataConnectionConfiguration" />
</property>
</bean>
<bean id="dataConnectionConfigurationFactory" class="org.apache.ftpserver.DataConnectionConfigurationFactory" />
<bean id="nioListener" factory-bean="listenerFactory" factory-method="createListener" />
<afs:server id="server" anon-enabled="false">
<afs:listeners>
<afs:listener name="default">
<ref bean="nioListener"/>
</afs:listener>
</afs:listeners>
<!-- other AFS config -->
</<afs:server>

spring mvc i18n: If key not in properties file, how to set default locale?

suppose if i don't have a key in my one of the properties file i get a exception like :
javax.servlet.ServletException: javax.servlet.jsp.JspTagException: No message found under code 'label.cancel' for locale 'en'.
suppose if it is not available in my messages_ch_CN.properties is there any way that if it is not present in that file it should check in messages_en_En file.
or is there any work around any one has implemented.
For example you have: 2 language
messages_ch_CN.properties /*in the property file lang=Chinese*/
messages_en_EN.properties /*in the property file lang=English*/
messages.properties /*in the property file lang=English default*/
messages.properties this is default property, which always contains every key used throughout your application.
and NAME-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<context:component-scan base-package="com.example.controller"/>
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:com/example/i18n/messages"/>
<property name="fallbackToSystemLocale" value="false"/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang"/>
</bean>
</mvc:interceptors>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en"/>
</bean>
</beans>
<property name="fallbackToSystemLocale" value="false"/> - says that, if you don't have property messages_ch_CN.properties or messages_en_EN.properties or in one of those property there is no necessary key, for example: title, spring will use messages.properties as default
if <property name="fallbackToSystemLocale" value="true"/> - spring uses user locale of deployment environment, but it not good because user's deployment environment, can different from the languages that we have provided. If user's locale different from the languages that we have provided, spring uses messages.properties.
One workaround would be to subclass the messageSource you're using (ie ReloadableResourceBundleMessageSource) and override it's resolveCode() so that:
it looks for a message for specified code and locale (by calling super.resolveCode(code, locale)).
if it doesn't find it, then it looks for one with default locale (by calling super.resolveCode(code, defaultLocale)).
Then use that newly created class as messageSource.
Always provide a default messages file (without locale specification), which always contains every key used throughout your application. It is not possible to look automatically for another locale than the chosen one without subclassing one of the ResourceBundleimplementations.

Resources