Configure JMX with Spring implementation of ehcache? - spring

I'm trying to follow the articles here & here to implement JMX for ehCache. My app uses the Spring implementation however & the config entries below get this exception:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'managementService' defined in class
path resource [trs.application.finance.businessactivites.xml]:
Unsatisfied dependency expressed through constructor argument with
index 0 of type [net.sf.ehcache.CacheManager]: Could not convert
constructor argument value of type
[org.springframework.cache.ehcache.EhCacheCacheManager] to required
type [net.sf.ehcache.CacheManager]: Failed to convert value of type
'org.springframework.cache.ehcache.EhCacheCacheManager' to required
type 'net.sf.ehcache.CacheManager'; nested exception is
java.lang.IllegalStateException: Cannot convert value of type
[org.springframework.cache.ehcache.EhCacheCacheManager] to required
type [net.sf.ehcache.CacheManager]: no matching editors or conversion
strategy found
Does spring have an implementation of net.sf.ehcache.management.ManagementService I can use? If so how do I configure it so I can have JMX support for ehcache in my app.
Note, the "managementService" & "mbeanServer" beans are what I added to try & get ehcache to register with jmx. "myCacheManager" already exists in my spring config & seems to work fine, as far ehcache alone goes.
<bean id="managementService" class="net.sf.ehcache.management.ManagementService"
init-method="init"
destroy-method="dispose">
<constructor-arg ref="myCacheManager"/>
<constructor-arg ref="mbeanServer"/>
<constructor-arg index="2" value="true"/>
<constructor-arg index="3" value="true"/>
<constructor-arg index="4" value="true"/>
<constructor-arg index="5" value="true"/>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true"/>
</bean>
<bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
</property>
</bean>

The problem is the way you wire your beans.
You do not want to use myCacheManager in the managementService, you really want to use the bean returned and passed as the cacheManager of myCacheManager.
So I suggest moving the following:
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
to a top level bean so that it can be injected in managementService.

Related

Connecting to multiple ActiveMQ Servers using Spring Integration XML Configuration

I have been trying for couple days to set up multiple ActiveMQ connections in Spring Integration using XML configuration.
I am using spring boot, SI looks for a bean called jmsConnectionFactory in the context and uses it. But what if I have to send/listen to jms messages from/to different ActiveMQ servers?
What I have right now is this:
<bean id="jmsConnectionFactory1"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</property>
<property name="sessionCacheSize" value="10" />
<property name="cacheConsumers" value="false" />
</bean>
<bean id="jmsConnectionFactory2"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.1.59:61616" />
</bean>
</property>
<property name="sessionCacheSize" value="10" />
<property name="cacheConsumers" value="false" />
</bean>
...
<jms:message-driven-channel-adapter channel="jmsInChannel" destination-name="queue.demo" />
<int:channel id="jmsInChannel" />
...
When trying to start the spring boot app I get this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'jmsConnectionFactory' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'jmsConnectionFactory' in 'ActiveMQXAConnectionFactoryConfiguration' not loaded because #ConditionalOnClass did not find required class 'javax.transaction.TransactionManager'
Action:
Consider revisiting the entries above or defining a bean named 'jmsConnectionFactory' in your configuration.
I came across this solution, https://stackoverflow.com/a/43401330/3367392 it's a java configuration. Also I looked into this but it's using camel https://stackoverflow.com/a/13288312/3367392
Is there a way to achieve the same for Spring Integration using XML configuration?
Ok so I got it, for a simple case I just had to add the right connectionFactory to the adapters like this
<jms:message-driven-channel-adapter channel="jmsInChannel"
destination-name="queue.demo"
connection-factory="jmsConnectionFactory1" />

Configure Spring bean by setting up the elastic 5.5.1 configuration settings and create a transport client bean

I am trying to use ElasticSearch Java API 5.5.1 and while trying to create a bean for PreBuiltTransportClient(TransportClient in ES 2.3) I am facing the below issue.
Error creating bean with name 'preBuildTransportClient' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Unsatisfied dependency expressed through constructor parameter 0: Could not convert argument value of type [org.elasticsearch.common.settings.Settings$Builder] to required type [org.elasticsearch.common.settings.Settings]: Failed to convert value of type [org.elasticsearch.common.settings.Settings$Builder] to required type [org.elasticsearch.common.settings.Settings]; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.elasticsearch.common.settings.Settings$Builder] to required type [org.elasticsearch.common.settings.Settings]: no matching editors or conversion strategy found
<bean id="settingsBean" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<bean id="builderObj" class="org.elasticsearch.common.settings.Settings" factory-method="builder" />
</property>
<property name="targetMethod" value="put" />
<property name="arguments">
<map>
<entry key="cluster.name">
<value>mycluster</value>
</entry>
</map>
</property>
</bean>
<bean id="transportClient" class="org.elasticsearch.transport.client.PreBuiltTransportClient">
<constructor-arg name="settings" ref="esSettingsBuilderStep2" />
<constructor-arg name="plugins">
<null />
</constructor-arg>
</bean>
Any suggestion for creating a bean for PreBuiltTransportClient?
Created a class and used that as bean with proper arguments worked for me.

context:property-placeholder how to reference the property bean

We have this existing property loader configuration in our spring context
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<util:list>
<value>hedging-service.properties</value>
</util:list>
</property>
</bean>
<!--Hedging properties bean that can be injected into other beans-->
<util:properties id="hedgingProperties" location="classpath:hedging-service.properties"/>
and there is a bean which references the hedgingProperties bean
<bean id="mailProcessor"
class="a.b.c.MailProcessor">
<property name="properties" ref="hedgingProperties"/>
...
</bean>
I'm refactoring the context to load from multiple property files and also avoid the duplicate definition of the properties. My first attempt is to use this bean in place of the two above
<context:property-placeholder location="classpath:hedging-service-core.properties,classpath:hedging-service.properties,classpath:icon.properties"/>
but how can I retain the alias or reference to the hedgingProperties bean when I use the context:property-placeholder?
The answer is a mixture context:property-placeholder and util:properties
<util:properties id="hedgingProperties" location="classpath:hedging-service.properties"/>
<context:property-placeholder properties-ref="hedgingProperties" />
<bean id="mailProcessor" class="a.b.c.MailProcessor">
<property name="properties" ref="hedgingProperties"/>
...
</bean>

<jee:jndi-lookup default-value and the use of classpath

I am really stuck on this one... Help! :)
I am using j2ee:jndi lookup for a property file. The following works fine:
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true" />
</constructor-arg>
</bean>
However, I want to handle the case where the jndi lookup fails but will fall back on a default file located in WEB-INF/classes folder. If I use the default-value as below, the webapp throws an exception complaining that it cannot find the file "classpath:myprops.properties"
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true"
default-value="classpath:myprops.properties" />
</constructor-arg>
</bean>
However, if I hard-code a specific path for default-value, then it works fine, but that is unacceptable as a final solution.
Thus, my issue is how to use "classpath:" so that it gets properly resolved?
This is the overall usage I'm employing:
<bean id="authServerProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="ignoreResourceNotFound" value="true"/>
<property name="location">
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true"
default-value="classpath:myprops.properties" />
</constructor-arg>
</bean>
</property>
.....
</bean>
Let Spring use its built-in PropertyEditor support to decide on the type of resource, rather than supplying an explicit FileSystemResource bean as this won't work with classpath resources (it needs to be configured with a path on the file system). Instead you should use something like
<bean id="authServerProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="ignoreResourceNotFound" value="true"/>
<property name="location" ref="myProps" />
</bean>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true"
default-value="classpath:myprops.properties"/>
Here we are setting the location to be a string value and allowing Spring to convert that to the appropriate resource type, so if you have
<env-entry>
<env-entry-name>myProps</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>file:///Users/something/myProps.properties</env-entry-value>
</env-entry>
in your web.xml, it will use a UrlResource with the given file URL, otherwise it will create a ClasspathResource to look for the file myprops.properties.

using a <jee:jndi-lookup string inside an instance of PropertyPlaceholderConfigurer

Environment: Windows server 2003, Spring 3.0, Tomcat 6
How can I reference a JNDI property inside a PropertyPlaceholderConfigurer?
Specifically, I'm using JNDI to look up a java.lang.String that represents a path to
a property file needed by my webapp
<jee:jndi-lookup id="mypropsfile1" jndi-name="myPropsFile1" resource-ref="true"/>
<jee:jndi-lookup id="mypropsfile2" jndi-name="myPropsFile2" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<array>
<value>how to use mypropsfile1 here ??</value>
<value>how to use mypropsfile2 here ??</value>
</array>
</property>
</bean>
My "jee:jndi-lookup"s are working AFAIK. My problem seems to be how to reference JNDI resources
inside the tag pair
Thanks in advance!
Mark
Your approach may not work Mark, this is because PropertyPlaceHolderConfigurer is a BeanFactoryPostProcessor and gets invoked at the point when the bean definitions are created, whereas the jndi lookup happens post this stage.
I saw an older Spring forum discussion item, which has a recommendation for an approach of using a jndi lookup based properties file, which may suit your needs:
I believe you will have to do something like this . I haven't tested it but basically the setLocations method in PropertyPlaceholderConfigurer takes in an array of Resource(In our case UrlResource - http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/core/io/UrlResource.html) which in turn has a constructor with the file path .
<jee:jndi-lookup id="mypropsfile1" jndi-name="myPropsFile1" default-value="file:///C:/defaultPath" resource-ref="true"/>
<jee:jndi-lookup id="mypropsfile2" jndi-name="myPropsFile2" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="mypropsfile1,mypropsfile2">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="mypropsfile1"/></constructor-arg>
</bean>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="myPropsFile2"/></constructor-arg>
</bean>
</list>
</property>
</bean>
I am not sure if there is a tag called in spring . Check this http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-introduction
I do this in Spring 3 using a map as follows:
<jee:jndi-lookup id="myJndiLookup" jndi-name="com.techtrip.spring.config.myJndiLookup"></jee:jndi-lookup>
<bean id="somethingWithMap" class="com.techtrip.foo.SomethingWithMap">
<property name="propMap">
<map>
<entry key="myJndiLookup" value-ref="myJndiLookup" />
</map>
</property>
</bean>
This works fine in most cases. You may run into trouble if you use AOP or something that wraps the bean in a Proxy class even if you set eager init correctly. A solution in that case is to directly access the somethingWithMap bean from the app context when needed using:
applicationContext.getBeansOfType(type, includeNonSingletons, allowEagerInit);
*Note that this will return a Map<String, T> where you can access the bean by name.
Not exactly for a single JNDI property, this is using a Properties reference instead, obtained through JNDI:
<!-- Lookup Properties reference through JNDI -->
<jee:jndi-lookup id="config-properties" jndi-name="resources/resource-name" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="config-properties">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<!-- Once the reference is obtained from JNDI, it can be used like any other reference -->
<property name="properties" ref="config-properties"></property>
</bean>

Resources