Blueprint CXF serviceFactories: Need an instance per request - osgi

I am using Apache Karaf, CXF, and Aries Blueprint.
I have a bundle which defines a number of JAX-RS services. By default, CXF will make these services singletons, but this will not work for me. I need a new instance to handle each request.
Referencing the CXF documentation, I tried to create JAX-RS ServiceFactories which return new instances of the services. The documentation had examples for Spring and I tried to Blueprint equivalent.
<reference id="groupService" interface="org.ozoneplatform.owf.server.service.api.GroupService"/>
<bean id="groups" class="org.ozoneplatform.owf.server.rest.GroupController" scope="prototype">
<property name="service" ref="groupService"/>
</bean>
<bean id="groupFactory" class="org.apache.cxf.blueprint.jaxrs.BlueprintResourceFactory">
<property name="beanId" value="groups" />
</bean>
<jaxrs:server id="ozoneplatform_cxf_endpoint" address="/owf">
<jaxrs:serviceFactories>
<ref bean="groupFactory" />
</jaxrs:serviceFactories>
Blueprint fails to start giving the error
org.osgi.service.blueprint.container.ComponentDefinitionException:
Error setting property: PropertyDescriptor <name: resourceProviders, getter: null, setter: [class org.apache.cxf.jaxrs.JAXRSServerFactoryBean.setResourceProviders(interface java.util.List)]

You must define "blueprintContainer" property for BlueprintResourceFactory instance as:
<bean id="groupFactory" class="org.apache.cxf.blueprint.jaxrs.BlueprintResourceFactory">
<property name="beanId" value="groups" />
<property name="blueprintContainer" ref="blueprintContainer"/>
</bean>
Where ref="blueprintContainer" is a reference to top-level manager (see 121.11 Blueprint Container)

Related

Spring boot unable to create multiple rabbit connection factories

I am trying to connect to and consume from two different clusters of rabbitmq using a spring boot app via xml. It works well when a single rabbit:connection-factory bean is created in the application context. However, when the second one is added, it fails to start the application with the error "Parameter 1 of method rabbitListenerContainerFactory in org.springframework.boot.autoconfigure.amqp.RabbitAnnotationDrivenConfiguration required a single bean, but 2 were found:". How do I go about creating different factories per cluster? Please suggest an alternative way of doing this, if it's not the right approach?
Here is the xml snippet:
<rabbit:connection-factory id="firstConnectionFactory" connection-factory="firstSpringConnectionFactory" />
<rabbit:connection-factory id="secondConnectionFactory" connection-factory="secondSpringConnectionFactory"/>
<bean id="firstSpringConnectionFactory"
class="org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean">
<property name="useSSL" value="${rabbitmq.ssl.enabled}" />
<property name="host" value="${rabbitmq.first.host}"/>
<property name="virtualHost" value="${rabbitmq.vhost}"/>
<property name="port" value="${rabbitmq.cluster.port}"/>
<property name="username" value="${rabbitmq.user}"/>
<property name="password" value="${rabbitmq.first.password}"/>
</bean>
<bean id="secondSpringConnectionFactory"
class="org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean">
<property name="useSSL" value="${rabbitmq.ssl.enabled}" />
<property name="host" value="${rabbitmq.second.host}"/>
<property name="virtualHost" value="${rabbitmq.vhost}"/>
<property name="port" value="${rabbitmq.cluster.port}"/>
<property name="username" value="${rabbitmq.user}"/>
<property name="password" value="${rabbitmq.second.password}"/>
</bean>
And the listener container code:
ConnectionFactory cf = rabbitConnectionFactory;//One of the connnection factories will be injected here from app context
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(cf);
container.setConcurrentConsumers(count);
container.addQueueNames(queueName);
container.setMessageListener(listener);
container.start();
Since you don't rely on the Spring Boot here and don't use Spring AMQP annotation support I suggest you to exclude RabbitAnnotationDrivenConfiguration from auto-configuration:
#EnableAutoConfiguration(exclude={RabbitAnnotationDrivenConfiguration.class})
spring.autoconfigure.exclude = org.springframework.boot.autoconfigure.amqp.RabbitAnnotationDrivenConfiguration
If you still need #RabbitListener somewhere in other place of your project, you only have a choice to build all the #EnableRabbit infrastructure manually.

How to configure flushMode property of OpenSessionInViewInterceptor of spring 3.1.4

As I am planning to update from "hibernate3" to "hibernate4" & "spring 3.0.5" to "spring 3.1.4".
I have configured OpenSessionInViewInterceptor in spring 3.0.5 so want to configure same in 3.1.4.
But I am not able to configure flushMode in OpenSessionInViewInterceptor of Spring 3.1.4;
My Previous setting for spring 3.0.5 was:
<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="flushMode">
<bean
id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_NEVER"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>
Now tried to configure same for spring 3.1.4 as below:
<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="flushMode">
<bean
id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_NEVER"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>
then it throws below exception:
org.springframework.beans.NotWritablePropertyException: Invalid property 'flushMode' of bean class [org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor]: Bean property 'flushMode' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
And there is no similar class found in alternate to org.springframework.orm.hibernate3.HibernateAccessor in spring 3.1.4
So my question is how to set flushMode property of OpenSessionInViewInterceptor of spring 3.1.4 ?
It looks like a mess, with unbound links to property accessors. I'd guess that a copy-paste job was done without much thinking about cleaning things up given the different inheritance hierarchies. I hate it when that happens…
Can you use the Hibernate 3 version instead? Yes, it really does appear to be there; here's the link: org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
Longer term, look more carefully whether the Hibernate 4 code does what you want without specifying the flag at all. Unfortunately, you'll have to ignore the documentation (at least for now) and study the source itself.

OpenEntityManagerInViewInterceptor for CXF

I have a Web service application based on JPA (Hibernate), Spring and CXF.
I am facing some lazy-load exceptions after transactional business methods (because I need some extra beans to be rendered in the rpesentation layer), and I wanted to give a try to the OpenSession/EntityManagerInView pattern.
Please do not argue this choice, we are just giving it a try.
The issue is that, since I am using CXFServlet, instead of standard Spring Servlet, I cannot use OpenEntityManagerInViewFilter in web.xml.
I cannot use either OpenEntityManagerInViewInterceptor which applies as a WebRequest Interceptor (and does not work with CXF interceptor/filters).
Finally I am aware of the HibernateInterceptor, an AOP proxy which wraps any method into a session. But still : this one is for the Hibernate API, not JPA API (I am using EntityManagerFactory, rather than SessionFactory).
So, are you aware of either :
A HibernateInterceptor for the JPA API (EntityManagerInterceptor ?)
A way to adapt a Spring WebRequestInterceptor into a JAX-RSfilter ?
Any other solution ?
Thanks in advance for your help.
Once again, I finally found what I wanted ...
There is actually a JpaInterceptor that does what I want (it seems deprecated though. I do not really understand why).
Here is the resulting configuration that works like a charm, with a bit of auto proxy by name :
<bean id="jpaInterceptor" class="org.springframework.orm.jpa.JpaInterceptor">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="jpaAutoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
<property name="beanNames">
<list>
<value>myService1</value>
<value>myService2</value>
<value>...</value>
</list>
</property>
<property name="interceptorNames">
<list><value>jpaInterceptor</value></list>
</property>
</bean>
<jaxrs:server id="services" address="/">
<jaxrs:serviceBeans>
<ref bean="myService1" />
<ref bean="myService2" />
<ref bean="..." />
</jaxrs:serviceBeans>
</jaxrs:server>

spring web flow enable scopes

Spring web flow provides additional bean scopes like flow, conversation, flash etc. I can define flow scope beans in flow.xml using var or i can set values to new scoped variables. How i can define it in spring application context xml file. I tried to use this pattern:
<bean id="abc" class="abc" scope="flow"/>
I got error that no scope defined. I searched on google and found this thing
http://blog.springsource.org/2007/05/08/spring-web-flow-bean-scopes-and-jsf/
but don't know how to enable it in spring web flow 2.3
try to define it in your application context:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="flow">
<bean class="org.springframework.webflow.config.scope.FlowScope"/>
</entry>
</map>
</property>
</bean>

host/role dependent spring configuration

I have a cluster of servers running a spring application. Some of the spring components need to be configured differently depending on the role their server is playing (primary, secondary, etc). I don't want to maintain separate spring config files for each role, rather I want to dynamically detect this when the application is started. Its almost like I want conditional bean instantiation (which doesn't exist in spring).
Q: What is the best way to achieve this type of configuration?
Example: Only the primary node in a cluster should create durable subscription to a JMS broker (which requires a globally unique JMS clientID). I can detect if the current host has this role by looking up the running server's hostname in a database and start this container manually (if my node happens to be primary); however, I don't want every node in the cluster to create a durable subscription (by instantiating this bean).
<bean id="auditrecordListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1" />
<property name="clientID" value="${server-hostname}" />
<property name="durable" value="true" />
<!-- only started on the primary node: via application listener -->
<property name="autoStartup" value="false" />
</bean>
Note, however there is no ${server-hostname} property in the spring container (at least that I know of)
If your code already conditionally starts the appropriate services based on object properties, you can use utility methods in the following manner:
<!-- Factory methods to determine properties -->
<bean id="hostname" class="MyUtil" factory-method="determineHostName"/>
<bean id="isHost" class="MyUtil" factory-method="isHost"/>
<bean id="auditrecordListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1" />
<property name="durable" value="true" />
<!-- Reference properties here -->
<property name="hostname" ref="hostname" />
<property name="autoStartup" ref="isHost" />
</bean>
To use a property of a singleton bean instead, use a PropertyPathFactoryBean:
<bean id="config" class="MyConfig"/>
<util:property-path id="hostname" path="config.hostname"/>
<util:property-path id="isHost" path="config.host"/>
You can implement a conditional instantiation logic
as a FactoryBean

Resources