Spring: Nested beans reference to another bean is not working - java

I am trying to use nested beans with a profile to setup an embedded jms broker when I am in dev mode. Here is my xml:
<beans ...>
...
other bean definition
...
<beans profile="embeddedBroker">
<!-- Configure an embedded ActiveMQ Broker with a TCP connector.
This broker is never set to start automatically by default, it is the broker service wrapper that
will take care to start it if configured to do so.
-->
<amq:broker id="jmsBroker" brokerId="EmbeddedBroker" brokerName="EmbeddedBroker"
persistent="false" useJmx="true" start="false">
<amq:plugins>
<!-- lets enable detailed logging in the broker but ignore ConnectionEvents -->
<amq:loggingBrokerPlugin logMessageEvents="true" logConnectionEvents="false"/>
<amq:timeStampingBrokerPlugin zeroExpirationOverride="1000" ttlCeiling="60000" futureOnly="true"/>
<amq:traceBrokerPathPlugin />
</amq:plugins>
<!-- Create a connector to give an external remote access to this broker. -->
<amq:transportConnectors>
<amq:transportConnector uri="tcp://127.0.0.1:35000" />
</amq:transportConnectors>
</amq:broker>
<!-- This broker service (wrapper) control the lifecycle of the jms broker defined above.
By default the internal broker will be initialized, but not started. It will usually be started only for
internal integration and unit tests.
-->
<bean id="jmsBrokerService" class="com.imetrik.global.common.jms.AMQBrokerService"
init-method="start"
destroy-method="stop">
<property name="broker" ref="jmsBroker" />
<property name="enabled" value="true" />
</bean>
</beans>
</beans>
But when I run my application with the correct profile, spring complain that the jmsBroker reference cannot be found!
Error creating bean with name 'jmsBrokerService' defined in class path resource [jms-beans.xml]: Cannot resolve reference to bean 'jmsBroker' while setting bean property 'broker';
Is there a way to fix that? Is it because the reference bean is not in the same namespace?
I know that if I put it out of the nested beans, it is working fine.
I am using Spring 4.1

Related

Connecting Tomcat to standalone Artemis Broker via JNDI

I want to define a jms ConnectionFactory as global resource in tomcat server.xml to connect my webapps to standalone Artemis server.
Unfortunately I couldn't find any official or clean manual for such a common use case that describes required libraries and configurations.
Can somebody show me an example?
I couldn't find any native Artemis based solution. Artemis server is ActiveMQ client compatible. So we can follow ActiveMQ manual for this purpose.
Add ActiveMQ client libraries to $CATALINA_HOME/lib
geronimo-jms_2.0_spec-1.0-alpha-2.jar
activemq-client-5.14.3.jar
geronimo-j2ee-management_1.1_spec-1.0.1.jar
hawtbuf-1.11.jar
slf4j-api-1.7.6.jar
Add global resource to $CATALINA_HOME/conf/server.xml
<Resource auth="Container"
name="jms/ConnectionFactory"
type="org.apache.activemq.ActiveMQConnectionFactory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
brokerURL="tcp://127.0.0.1:61616"
brokerName="MyActiveMQBroker"/>
Add resource link to $CATALINA_HOME/conf/context.xml
<ResourceLink name="/ConnectionFactory"
global="jms/ConnectionFactory"
type="javax.jms.ConnectionFactory"/>
Look up connection factory in app context
<bean id="jmsConnectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/ConnectionFactory" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory"/>
</bean>

using a Java blueprint service defintion

I can't get the blueprint right for using a service locally. The OSGi server (karaf) displays GracePeriod and eventually a timeout waiting on ILookupMfgService.
If I remove the reference line the bundle starts and has an ILookupMfgService available.
Any suggestions on what I'm doing wrong?
Thanks for helping with my learning!
Timothy
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance
http://aries.apache.org/xmlns/jpa/v1.0.0 http://aries.apache.org/xmlns/jpa/v1.0.0
http://aries.apache.org/xmlns/transactions/v1.0.0 http://aries.apache.org/xmlns/transactions/v1.0.0
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 ">
<!-- implemenation of the service -->
<bean id="lookupMfgServiceStubImpl" class="com.services.jpa.LookupMfgServiceStub" scope="singleton"
init-method="init" />
<!-- create a service with the implementation -->
<service id="lookupMfgServiceStubLocal" ref="lookupMfgServiceStubImpl" interface="com.services.ILookupMfgService" />
<!-- create a reference for injecting into another bean - this line causes the GracePeriod / timeout -->
<reference id="lookupMfgServiceStubRef" interface="com.services.ILookupMfgService" availability="mandatory" ctivation="eager" />
<bean id="EntityImpl" class="com.services.jpa.Entity" scope="singleton" init-method="init">
<!-- use the service - won't work without the reference above being valid -->
<property name="lookupMfg" ref="lookupMfgServiceRef" />
</bean>
</blueprint>
without reference line
karaf#root()> services -p 123
com.server.services (123) provides:
----------------------------------------
objectClass = [com.services.ILookupMfgService]
osgi.service.blueprint.compname = lookupMfgServiceStubImpl
service.id = 932
----
You must not declare a mandatory reference to service exposed in the same blueprint/bundle. The container gets confused because it wants to start a service with a reference to a service that is not yet there (himself) which results in an unrecoverable GracePeriod.
A rough analogy of a reference is a Java Import from another package. The analogy of a service is a public class.
You need the import (=reference) if you want to use a class from a different package.
In your example you do not need the reference because you are within your bundle. You can reference your declared Bean directly instead:
<!-- implemenation of the service -->
<bean id="lookupMfgServiceStubImpl" class="com.services.jpa.LookupMfgServiceStub" scope="singleton"
init-method="init" />
<!-- create a service with the implementation -->
<service id="lookupMfgServiceStubLocal" ref="lookupMfgServiceStubImpl" interface="com.services.ILookupMfgService" />
<bean id="EntityImpl" class="com.services.jpa.Entity" scope="singleton" init-method="init">
<!-- use the service - won't work without the reference above being valid -->
<property name="lookupMfg" ref="lookupMfgServiceStubImpl" />
</bean>
p.s. If no no other bundle needs your LookupMfgService then you can even leave out the service declaration.

Externalize properties in Tomcat

I would like to configure a series of environment-dependant settings as an external resource, so that the same WAR artifact can be configured in any application server.
In Glassfish I rememeber that I just created a .properties file using the built-in Properties Resource JNDI Factory, and it worked like a charm, but there's no such thing in Tomcat.
I tried defining a java.net.URL and a java.lang.String to define just the path that this file is held in, but I get the following error:
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/c://app.properties]
So what would be a good way to create an environment-agnostic set of properties for my application?
PS: this is how I define my properties in Spring:
<jee:jndi-lookup id="appProperties" jndi-name="java:comp/env/url/urlAppProperties" />
<bean id="application-properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>#{ appProperties }</value>
</list>
</property>
</bean>
You can add external configuration values to the JNDI context using Tomcat's resource configuration elements. As described in the Tomcat documentation, you can define a <GlobalNamingResources> element in your server.xml listing a set of configuration values which are available to all contexts (web applications) on that server:
Example taken from the Tomcat docs:
<GlobalNamingResources ...>
...
<Environment name="maxExemptions" value="10"
type="java.lang.Integer" override="false"/>
...
</GlobalNamingResources>
These environment variables are then available via JDNI in the java:comp/env context. In order to use such variables in a web application, you have to link to them in the individual context.xml configuration files using the <ResourceLink> element.
<Context>
<ResourceLink name="maxExemptions" global="maxExemptions" type="java.lang.Integer"/>
</Context>
With this set up, you can access these values through the standard JNDI API.

spring hbase properties : where to specify apache config timeout?

Where do I set properties like 'hbase.client.retries.number' when using hbase.version : 1.1.1
Using xml to configure spring. In my xml:
<context:property-placeholder location="classpath:webr/hbase.properties" />
<context:component-scan base-package="com.mine.xx" />
<hdp:configuration id="hadoopConfiguration">
fs.defaultFS=file:///usr/local/XX
</hdp:configuration>
<!-- configuration-ref="hadoopConfiguration" -->
<hdp:hbase-configuration configuration-ref="hadoopConfiguration"
zk-quorum="${hbase.zk.host}" zk-port="${hbase.zk.port}" />
But when I set (in webr/hbase.properties) :
hbase.client.retries.number=0
zookeeper.session.timeout=38000
zookeeper.recovery.retry=0
hbase.rpc.timeout=29000
zookeeper.recovery.retry=0
They do not get picked up (the program hangs for more than 3 minutes) after a scan is sent.
The hadoop install is on my lan.

JMS message not picked up by Spring listener

I have a Spring app running inside a standalone JBoss EAP 6.2 (with its embedded HornetQ provider).
Messages are succcesfully put on the queue (I can see them in jboss-eap-6.2\standalone\data\messagingjournal\hornetq-data-1.hq because the queue is durable), but not picked up by the listener (a breakpoint inside the listener is not hit). I suspect something is missing from or wrong in the configuration but cannot see what. JBoss starts without any validation errors.
First, the excerpt from Spring's applicationContext.xml:
The JNDI names of the connection factory and queue match those in JBoss' standalone-full.xml
<jee:jndi-lookup id="jmsConnectionFactory" jndi-name="java:/JmsXA" resource-ref="false" proxy-interface="javax.jms.ConnectionFactory"/>
<jee:jndi-lookup id="myQueue" jndi-name="java:jboss/exported/jms/queue/myQueue"/>
<bean id="myHandler" class="com.example.MyHandler" />
<jms:listener-container destination-type="queue" acknowledge="auto" connection-factory="jmsConnectionFactory">
<jms:listener destination="java:jboss/exported/jms/queue/myQueue" ref="myHandler" method="processMessage" />
</jms:listener-container>
The message handler is declared as a Spring component and the class and method names match what is declared above:
#Component
public class MyHandler {
public void processMessage(MyMessage delaySendTransfer) {
//...
}
By default, Spring use the DynamicDestinationResolver for the listener container so it expects to receive a bean reference in the destination attribute of the listener. Since you are using a JNDI name, you should set the destination resolver strategy to jndiDestinationResolver.
<jms:listener-container destination-resolver="jndiDestinationResolver" destination-type="queue" acknowledge="auto" connection-factory="jmsConnectionFactory">
<jms:listener destination="java:jboss/exported/jms/queue/myQueue" ref="myHandler" method="processMessage" />
</jms:listener-container>
Replacing the destination attribute value with the bean reference should also do the trick :
<jms:listener-container destination-type="queue" acknowledge="auto" connection-factory="jmsConnectionFactory">
<jms:listener destination="myQueue" ref="myHandler" method="processMessage" />
</jms:listener-container>

Categories