Apache Camel JPA: Connect to two database instances - apache

Is there an obvious way to use two JPA consumers/producers in the Camel Spring DSL to talk to two different database instances? I tried to configure two EntityManagerFactory instances pointing to two Persistence Units but end up with the following when error :(
Caused by: org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: Found 2 beans of type: interface javax.persistence.EntityManagerFactory. Only one bean expected.
Camel Version: 2.13.2

You might have to make 2 entity manager factories, and have them point at different persistence units.
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="primary" />
</bean>
<bean id="entityManagerFactory2"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="secondary" />
</bean>
then when you set up the jpa bean, you can specify two different origins
<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="jpa2" class="org.apache.camel.component.jpa.JpaComponent">
<property name="entityManagerFactory" ref="entityManagerFactory2" />
<property name="transactionManager" ref="transactionManager" />
</bean>
and use:
<from uri="jpa://
or
<from uri="jpa2://

Related

Multiple Persistence Store for Apache Ignite

I have one use case where I have to support multiple persistence store for my ignite cluster,For example Cache A1 should be primed from Database db1 and Cache B1 should be primed from database db2. can this be done?.In ignite Configuration XML I can only provide one persistence store details,
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Datasource for Persistence. -->
<bean name="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:roc12c" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
In my CacheStore implementation I can only access this Database right?.
I've not tried this, but if its similar to other bean-configured systems. You should be able to create another bean with a different name and configuration. Then in your cache configuration for A1 and B1 specify the different data sources. That being said, I'm guessing that theoretically.
It may be that you are already doing so, but I can't tell from your question. If you instead choose to implement your caches in this manner https://apacheignite.readme.io/docs/persistent-store you can definitely configure two caches to have different data sources. This is how I'm currently implementing multiple caches. In the cache store I use I specifically call out which database to go to.
Here is a cache configuration I use for mine.
<property name="cacheConfiguration">
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<!-- Set a cache name. -->
<property name="name" value="recordData"/>
<property name="rebalanceMode" value="ASYNC"/>
<property name="cacheMode" value="PARTITIONED"/>
<property name="backups" value="1"/>
<!-- Enable Off-Heap memory with max size of 10 Gigabytes (0 for unlimited). -->
<property name="memoryMode" value="OFFHEAP_TIERED"/>
<property name="offHeapMaxMemory" value="0"/>
<property name="swapEnabled" value="false"/>
<property name="cacheStoreFactory">
<bean class="javax.cache.configuration.FactoryBuilder" factory-method="factoryOf">
<constructor-arg value="com.company.util.MyDataStore"/>
</bean>
</property>
<property name="readThrough" value="true"/>
<property name="writeThrough" value="true"/>
</bean>
</property>
Cache store is configured per cache, so you just need to inject different data sources to different stores. What you showed is just a standalone data source bean, it's not even a part of IgniteConfiguration. You can have multiple data source beans with different IDs.

can not resolve property tag with job parameter

I am trying to concatenate the job parameter, #{jobParameters['arg1']} with myfeed.query to dynamically pick the right query from the properties file. But it's not getting resolved.
below is the exception log
Caused by: org.springframework.jdbc.BadSqlGrammarException: Executing query; bad SQL grammar [${myfeed.queryZONE1}]
below is the code snippet in the xml file.
<bean id="itemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<value>${myfeed.query#{jobParameters['arg1']}}</value>
</property>
<property name="rowMapper">
<bean class="com.sgcib.loa.matrix.mapper.MyFeedRowMapper" />
</property>
</bean>
To do that, you will need to declare explicit properties for your PropertyPlaceholderConfigurer :
<bean id="propertiesConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="properties" />
</bean>
<bean id="properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>file:xxxxxxx.properties</value>
</property>
</bean>
Then using Spring Expression Language (spEL), you can get the right property with :
<property name="sql" value="#{properties.getProperty('myfeed.query' + jobParameters['arg1'])}" /></property>
Note that this solution maintains compatibility with ${...} syntax.
The above solution does not work, tested solution is One ItemReader, 2 SQL Query, jdbcTemplate?
http://incomplete-code.blogspot.in/2013/06/dynamically-switch-sql-statements-in.html

Access activemq Poolable Connection factory as OSGI service

I am using fuse 6.0 and activemq 5.8. Instead of defining activemq poolable connection factory in each bundle, it makes sense to define in a common bundle and expose it as osgi service. I created blue print file in FUSE_HOME/etc and opened an osgi service like this.
<osgix:cm-properties id="prop" persistent-id="xxx.xxx.xxx.properties" />
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${xxx.url}" />
<property name="userName" value="${xxx.username}" />
<property name="password" value="${xxx.password}" />
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="${maxconnections}" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<service ref="pooledConnectionFactory" interface="javax.jms.ConnectionFactory">
<service-properties>
<entry key="name" value="localhost"/>
</service-properties>
</service>
and when i try to access this service in both blueprint files and spring text files like this
<reference id="pooledConnectionFactory" interface="javax.jms.ConnectionFactory"/>
bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="concurrentConsumers" value="${xxx.concurrentConsumers}"/>
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
but I am getting following expection during bundles startup.
Failed to add Connection ID:PLNL6237-55293-1401929434025-11:1201, reason: java.lang.SecurityException: User name [null] or password is invalid.
I even defined compendium definition in my bundles.
How can i solve this problem? any help is appreciated.
I found this online https://issues.apache.org/jira/i#browse/SM-2183
Do i need to upgrade?
It looks to me like you're using the property placeholders incorrectly. First of all, you should know what osgix:cm-properties only exposes the properties at the persistent id that you specify. You can treat it like a java.util.Properties object, and even inject it into a bean as one. This does however mean that it makes no attempt to resolve the properties.
To resolve properties, use spring's property placeholder configurer.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="prop"/>
</bean>
P.S. The persistent id of cm-properties is the name of the file, not including the file type. You don't need the .properties at the end.

Spring Security with LDAP and custom UserDetailsContextMapper

I am trying to make Spring Security 3.05 to work with a modified UserDetailsContextMapper so that i can get a few more info out of LDAP they way i need to, a task that seems fairly straightforward, but had no success.
I have configured Spring Security to use LDAP authentication with the following beans:
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldaps://192.168.1.102:636" />
<property name="userDn" value="manager" />
<property name="password" value="password" />
</bean>
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userSearch">
<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="" />
<constructor-arg index="1" value="(mail={0})" />
<constructor-arg index="2" ref="contextSource" />
</bean>
</property>
</bean>
</constructor-arg>
<property name="userDetailsContextMapper" ref="myContextMapper" />
</bean>
However even though i have defined myContextMapper as:
<bean id="myContextMapper" class="com.mypackage.MyLDAPUserDetailsMapper">
<property name="rolePrefix" value="TEST_PREFIX" />
</bean>
it does not work. meaning that the custom mapper is ignored (i get no debug output whatsoever).
p.s. applicationContext-security.xml can be seen below and apart from the custom UserDetailsMapper that's been ignored, authentication and role assignment is working fine.
<authentication-manager>
<ldap-authentication-provider server-ref="contextSource"/>
</authentication-manager>
You don't need to configure the in-built UserDetailsContextMapper classes. Spring Security automatically picks up the correct UserDetailsContextMapper based on the type of LdapUserDetails class requested, which is configured by user-details-class attribute of ldap-authentication-provider. If you are using your own context mapper then configure it using the attribute user-context-mapper-ref.

How to Configure SSL over Database in Spring?

I want to add SSL security in the Database layer. I am using Struts2.1.6, Spring 2.5, JBOSS 5.0 and Informix 11.5. Any idea how to do this?
I have researched through a lot on the internet but could not find any solution.
Please suggest!
Here is my datasource and entity manager beans which is working perfect without SSL:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="INFORMIX" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.informix.jdbc.IfxDriver" />
<property name="url"
value="jdbc:informix-sqli://SERVER_NAME:9088/DB_NAME:INFORMIXSERVER=SERVER_NAME;DELIMIDENT=y;" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="minIdle" value="2" />
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="false">
<property name="targetObject" ref="dataSource" />
<property name="targetMethod" value="addConnectionProperty" />
<property name="arguments">
<list>
<value>characterEncoding</value>
<value>UTF-8</value>
</list>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" scope="prototype">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
Thankyou very much for your suggestion. So basically I need to set something like this in my applicationContext.xml, Please correct me if I am wrong:
<property name="username" value="username" />
<property name="password" value="password" />
**<property name="sslConnection" value="true" />**
<property name="minIdle" value="2" />
But how do I set the SSL certificate in java runtime. The link which you have provided is good but for some reason I am not able to follow. Please put your suggestion.
Using SSL for the communication between an application and a database is something that has to be supported by the database server (and the JDBC driver).
According to the documentation, this is supported by Informix Dynamic Server (IDS) since version 11.50.
You can use SSL support in your Java applications if you use IBM Data Server Driver for JDBC and SQLJ type 4 connectivity to DB2® for z/OS® Version 9 or later, to DB2 Database for Linux®, UNIX®, and Windows® Version 9.1, Fix Pack 2 or later, or to IBM Informix® Dynamic Server (IDS) Version 11.50 or later.
(...)
To use SSL connections, you need to:
Configure connections to the data source to use SSL. (link)
Configure your Java Runtime Environment to use SSL. (link)
The documentation should help.
If you're using a version of IDS prior to 11.50, then I'm afraid you'll have to use SSH tunneling.