mybatis config problem - database

I'm new to MyBatis.
Ive been trying to configure mybatis in a webservice I'm writing but with no luck yet.
What I've done already is,
UserInfoMapper interface
UserInfoMapper.xml with mapper namespace with my UserInfoMapper interface and a select
mybatis-config.xml with typeAlias to use as result type in UserInfoMapper.xml
dataSource bean for oracle (I get connected) in datasourceContext.xml
org.mybatis.spring.mapper.MapperScannerConfigurer bean with basePackage pointing to my UserInfoMapper interface in datasourceContext.xml
sqlSessionFactory bean ie. org.mybatis.spring.SqlSessionFactoryBean with property for my dataSource and configLocation
userInfoMapper bean ie. org.mybatis.spring.mapper.MapperFactoryBean with property mapperInterface (value="is.simnn.act.web.ngs.persistence.UserInfoMapper") and sqlSessionFactory property (ref="sqlSessionFactory") in datasourceContext.xml
then in my applicationContext.xml I have following,
<import resource="classpath:META-INF/wsContext.xml" />
<import resource="classpath:META-INF/db/datasourceContext.xml" />
In my test case I keep getting NullPointerException when I call jaxws:endpoint and it leads me to my UserInfoMapper interface.
Any idea or hints to what might be wrong with my config?
Thanks,
Gunnlaugur

It is hard to comment without having more information. Can you post your UserInfoMapper.java interface, your UserInfoMapper.xml and your stack trace, please? Are you certain that the method name in your interface matches the ID of your SELECT in the XML?

Related

camel - spring:bean syntax with dynamic class casting

I'm attempting to convert the following Java object initalization with dynamic class casting to camel spring bean syntax. I'm adding my broken spring bean sample as well. I dont have much familiarity with spring beans, so would very much appreciate some input. The Java syntax is:
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
STSAssumeRoleSessionCredentialsProvider credentials = new STSAssumeRoleSessionCredentialsProvider.Builder(
"arn:aws:iam::***:role/myRole-QA", "sessionName").build();
and broken spring bean:
<spring:bean id="sqsCredentials" class="com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider.Builder" >
<spring:constructor-arg index="0" value="arn:aws:iam:***:role/myRole-QA" />
<spring:constructor-arg index="1" value="sessionName" />
<spring:property name="targetMethod">
<spring:value>build</spring:value>
</spring:property>
</spring:bean>
I'm not sure if what I have for method build is correct, but there are two classes at play: .Builder and just STSAssumeRoleSessionCredentialsProvider. So Builder class returns STSAssumeRoleSessionCredentialsProvider. Most likely i have more then one issue to solve here, but the error I think is related to class mismatch ... much appreciate your time:
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'targetMethod' of bean class
[com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider$Builder]: Bean property 'targetMethod' is not writable
or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

Spring boot Auto connection to database [duplicate]

I have a nice little Spring Boot JPA web application. It is deployed on Amazon Beanstalk and uses an Amazon RDS for persisting data. It is however not used that often and therefore fails after a while with this kind of exception:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 79,870,633 milliseconds ago.
The last packet sent successfully to the server was 79,870,634 milliseconds ago. is longer than the server configured value of 'wait_timeout'.
You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
I am not sure how to configure this setting and can not find information on it on http://spring.io (a very good site though). What are some ideas or pointers to information?
I assume that boot is configuring the DataSource for you. In this case, and since you are using MySQL, you can add the following to your application.properties up to 1.3
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
As djxak noted in the comment, 1.4+ defines specific namespaces for the four connections pools Spring Boot supports: tomcat, hikari, dbcp, dbcp2 (dbcp is deprecated as of 1.5). You need to check which connection pool you are using and check if that feature is supported. The example above was for tomcat so you'd have to write it as follows in 1.4+:
spring.datasource.tomcat.testOnBorrow=true
spring.datasource.tomcat.validationQuery=SELECT 1
Note that the use of autoReconnect is not recommended:
The use of this feature is not recommended, because it has side effects related to session state and data consistency when applications don't handle SQLExceptions properly, and is only designed to be used when you are unable to configure your application to handle SQLExceptions resulting from dead and stale connections properly.
The above suggestions did not work for me.
What really worked was the inclusion of the following lines in the application.properties
spring.datasource.testWhileIdle = true
spring.datasource.timeBetweenEvictionRunsMillis = 3600000
spring.datasource.validationQuery = SELECT 1
You can find the explanation out here
Setting spring.datasource.tomcat.testOnBorrow=true in application.properties didn't work.
Programmatically setting like below worked without any issues.
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
#Bean
public DataSource dataSource() {
PoolProperties poolProperties = new PoolProperties();
poolProperties.setUrl(this.properties.getDatabase().getUrl());
poolProperties.setUsername(this.properties.getDatabase().getUsername());
poolProperties.setPassword(this.properties.getDatabase().getPassword());
//here it is
poolProperties.setTestOnBorrow(true);
poolProperties.setValidationQuery("SELECT 1");
return new DataSource(poolProperties);
}
I just moved to Spring Boot 1.4 and found these properties were renamed:
spring.datasource.dbcp.test-while-idle=true
spring.datasource.dbcp.time-between-eviction-runs-millis=3600000
spring.datasource.dbcp.validation-query=SELECT 1
whoami's answer is the correct one. Using the properties as suggested I was unable to get this to work (using Spring Boot 1.5.3.RELEASE)
I'm adding my answer since it's a complete configuration class so it might help someone using Spring Boot:
#Configuration
#Log4j
public class SwatDataBaseConfig {
#Value("${swat.decrypt.location}")
private String fileLocation;
#Value("${swat.datasource.url}")
private String dbURL;
#Value("${swat.datasource.driver-class-name}")
private String driverName;
#Value("${swat.datasource.username}")
private String userName;
#Value("${swat.datasource.password}")
private String hashedPassword;
#Bean
public DataSource primaryDataSource() {
PoolProperties poolProperties = new PoolProperties();
poolProperties.setUrl(dbURL);
poolProperties.setUsername(userName);
poolProperties.setPassword(password);
poolProperties.setDriverClassName(driverName);
poolProperties.setTestOnBorrow(true);
poolProperties.setValidationQuery("SELECT 1");
poolProperties.setValidationInterval(0);
DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
return ds;
}
}
I have similar problem. Spring 4 and Tomcat 8. I solve the problem with Spring configuration
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="initialSize" value="10" />
<property name="maxActive" value="25" />
<property name="maxIdle" value="20" />
<property name="minIdle" value="10" />
...
<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />
</bean>
I have tested. It works well! This two line does everything in order to reconnect to database:
<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />
In case anyone is using custom DataSource
#Bean(name = "managementDataSource")
#ConfigurationProperties(prefix = "management.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
Properties should look like the following. Notice the #ConfigurationProperties with prefix. The prefix is everything before the actual property name
management.datasource.test-on-borrow=true
management.datasource.validation-query=SELECT 1
A reference for Spring Version 1.4.4.RELEASE
As some people already pointed out, spring-boot 1.4+, has specific namespaces for the four connections pools. By default, hikaricp is used in spring-boot 2+. So you will have to specify the SQL here. The default is SELECT 1. Here's what you would need for DB2 for example:
spring.datasource.hikari.connection-test-query=SELECT current date FROM sysibm.sysdummy1
Caveat: If your driver supports JDBC4 we strongly recommend not setting this property. This is for "legacy" drivers that do not support the JDBC4 Connection.isValid() API. This is the query that will be executed just before a connection is given to you from the pool to validate that the connection to the database is still alive. Again, try running the pool without this property, HikariCP will log an error if your driver is not JDBC4 compliant to let you know. Default: none
For those who want to do it from YAML with multiple data sources, there is a great blog post about it: https://springframework.guru/how-to-configure-multiple-data-sources-in-a-spring-boot-application/
It basically says you both need to configure data source properties and datasource like this:
#Bean
#Primary
#ConfigurationProperties("app.datasource.member")
public DataSourceProperties memberDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("app.datasource.member.hikari")
public DataSource memberDataSource() {
return memberDataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
Do not forget to remove #Primary from other datasources.

Problems accessing datasource in Karaf 4 from Apache Camel

I've created a datasource in Karaf 4 (ServiceMix 7) that works from the karaf console - I can list tables, execute queries and so on.
My issue is when I try to use it from my Camel route.
Excerpt from my blueprint:
...
<reference filter="(osgi.jndi.service.name=jdbc/erp)" id="erpDataSource" interface="javax.sql.DataSource"/>
...
<to id="erpSelectQuery" uri="jdbc:erpDataSource"/>
...
It finds my dataSource but the blueprint can't start due to:
"java.lang.IllegalArgumentException: connectionFactory must be specified"
My datasource was created using:
jdbc:ds-create -dbName erp -dt DataSource -dn mysql -u erp -dc com.mysql.jdbc.Driver -p pre jdbc/erp
I'm at loss here
I have never done it via the jdbc command syntax I followed the guides from the Ops4J Wiki On Datasource creation which I like for one reason alone, this method creates a simple text file that can be administered by not just a Java developer, i.e. it is easier to modify and troubleshoot.
For the sake of not subjecting my answer to link rot I will just outline the procedure here.
Create a datasource configuration file(simple text file) in /servicemixhome/etc with the following naming convention org.ops4j.datasource-give_your_datasource_a_name.cfg .
In the config file configure the appropriate settings an example of mine looks like this:
osgi.jdbc.driver.class = com.mysql.jdbc.Driver
databaseName=dhData
user=foo
url=jdbc:mysql://192.199.199.199:3306/dhData
password=somepassword
dataSourceName=myDSName
Make sure you installed the ops4j required features:
feature:install pax-jdbc-mysql pax-jdbc-config
Now list the datasources using the following syntax:
karaf#root()> service:list javax.sql.DataSource
This will echo something like the list below back.
[javax.sql.DataSource]
----------------------
osgi.jdbc.driver.class = com.mysql.jdbc.Driver
databaseName=dhData
user=foo
url=jdbc:mysql://192.199.199.199:3306/dhData
password=somepassword
dataSourceName=myDSName
Provided by :
OPS4J Pax JDBC Config (216)
At this point you can reference the datasource usign an osgi filter in the blueprint.xml with the following syntax:
<reference filter="(&(objectClass=javax.sql.DataSource)(dataSourceName=myDSName ))" id="myData" interface="javax.sql.DataSource"/>
Then to reference this as property of a bean for example you could do the following:
<bean class="foo.bar" id="ImsCbrEventsBean">
<property name="dataSource" ref="myData"/>
</bean>
Keep in mind this creates a singular connection to a database and you should really create a connection pool.
This can be done by installing the pax-jdbc-pool-dbcp2 feature or any of the other connection pools but use only one at a time, then modifying the datasource config file to carry appropriate information like the example below:
osgi.jdbc.driver.name = mysql
databaseName=dhData
user=foo
url=jdbc:mysql://192.199.199.199:3306/dhData
password=somepassword
dataSourceName=myDSName
jdbc.pool.maxTotal=32
jdbc.pool.blockWhenExhausted=true
jdbc.pool.lifo=false
jdbc.pool.maxIdle=24
jdbc.pool.maxWaitMillis=5000
jdbc.pool.minEvictableIdleTimeMillis=1800000
jdbc.pool.minIdle=16
jdbc.pool.numTestsPerEvictionRun=3
jdbc.pool.softMinEvictableIdleTimeMillis=-1
jdbc.pool.testOnBorrow=true
jdbc.pool.testOnCreate=true
jdbc.pool.testOnReturn=true
jdbc.pool.testWhileIdle=true
jdbc.pool.timeBetweenEvictionRunsMillis=3600000

Why does Jasypt try to decrypt Camel Property Placeholders, regardless of the ENC( prefix?

In my Blueprint application deployed in JBoss Fuse 6.1.0-379, I want to secure the password I use for creating a database connection. I read this article and added <enc:property-placeholder> to the blueprint configuration. However my blueprint configuration has many property placeholders, and it seems that the Jasypt Placeholder Resolver is trying to decrypt all the placeholders I define in my Camel Context. When the Blueprint Context starts up, I get the following exception:
11:59:51,233 | ERROR | t-379-dmz/deploy | BlueprintCamelContext | 151 - org.apache.camel.camel-blueprint - 2.12.0.redhat-610379 | Error occurred during starting Camel: CamelContext(camel-5) due Failed to create route route7: Route(route7)[[From[{{uri}}]] -> [Log[logging]]] because of Failed to resolve endpoint: {{uri}} due to: org.jasypt.exceptions.EncryptionOperationNotPossibleException
org.apache.camel.FailedToCreateRouteException: Failed to create route route7: Route(route7)[[From[{{uri}}]] -> [Log[logging]]] because of Failed to resolve endpoint: {{uri}} due to: org.jasypt.exceptions.EncryptionOperationNotPossibleException
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:182)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:778)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:1955)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:1705)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:1579)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:1547)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.blueprint.BlueprintCamelContext.start(BlueprintCamelContext.java:177)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
at org.apache.camel.blueprint.BlueprintCamelContext.maybeStart(BlueprintCamelContext.java:209)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
at org.apache.camel.blueprint.BlueprintCamelContext.serviceChanged(BlueprintCamelContext.java:147)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:934)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:795)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:544)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4666)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.Felix.registerService(Felix.java:3674)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:347)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.registerService(BlueprintContainerImpl.java:448)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:383)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:261)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:270)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:233)[9:org.apache.aries.blueprint.core:1.0.1.redhat-610379]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)[11:org.apache.aries.util:1.0.1.redhat-610379]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)[11:org.apache.aries.util:1.0.1.redhat-610379]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)[11:org.apache.aries.util:1.0.1.redhat-610379]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)[11:org.apache.aries.util:1.0.1.redhat-610379]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)[11:org.apache.aries.util:1.0.1.redhat-610379]
at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1103)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:696)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:484)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4650)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.Felix$4.run(Felix.java:2123)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.Felix.runInContext(Felix.java:2147)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.Felix.startBundle(Felix.java:2121)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)[org.apache.felix.framework-4.0.3.redhat-610379.jar:]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1247)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1219)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.startAllBundles(DirectoryWatcher.java:1208)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:503)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:291)[7:org.apache.felix.fileinstall:3.3.11.redhat-610379]
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: {{uri}} due to: org.jasypt.exceptions.EncryptionOperationNotPossibleException
at org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:480)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.util.CamelContextHelper.getMandatoryEndpoint(CamelContextHelper.java:71)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.model.RouteDefinition.resolveEndpoint(RouteDefinition.java:192)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:106)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:112)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.model.FromDefinition.resolveEndpoint(FromDefinition.java:72)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultRouteContext.getEndpoint(DefaultRouteContext.java:88)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:890)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:177)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
... 38 more
Caused by: org.apache.camel.RuntimeCamelException: org.jasypt.exceptions.EncryptionOperationNotPossibleException
at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1363)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1005)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.blueprint.BlueprintPropertiesParser.parseProperty(BlueprintPropertiesParser.java:137)[151:org.apache.camel.camel-blueprint:2.12.0.redhat-610379]
at org.apache.camel.component.properties.DefaultPropertiesParser.createPlaceholderPart(DefaultPropertiesParser.java:201)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.component.properties.DefaultPropertiesParser.doParseUri(DefaultPropertiesParser.java:105)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.component.properties.DefaultPropertiesParser.parseUri(DefaultPropertiesParser.java:51)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:160)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:119)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultCamelContext.resolvePropertyPlaceholders(DefaultCamelContext.java:1155)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
at org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:478)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
... 46 more
Caused by: org.jasypt.exceptions.EncryptionOperationNotPossibleException
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:918)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:725)
at org.apache.karaf.jaas.jasypt.handler.EncryptablePropertyPlaceholder.getProperty(EncryptablePropertyPlaceholder.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.7.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_25]
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_25]
at org.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1001)[143:org.apache.camel.camel-core:2.12.0.redhat-610379]
... 54 more
I created a test bundle with a Blueprint Context which contains only one placeholder property defined in the Camel Context, without using the encrypted ENC() placeholder syntax. I just added <enc:property-placeholder> and the bundle failed to start with same exception (org.jasypt.exceptions.EncryptionOperationNotPossibleException).
Is this desired behavior?
My Blueprint configuration:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
xmlns:enc="http://karaf.apache.org/xmlns/jasypt/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
<cm:property-placeholder persistent-id="encrypt.config" update-strategy="reload" >
<cm:default-properties>
<cm:property name="uri" value="timer://foo?fixedRate=true&period=6000"/>
</cm:default-properties>
</cm:property-placeholder>
<enc:property-placeholder>
<enc:encryptor class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config">
<bean class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWithMD5AndDES" />
<property name="password" value="password" />
</bean>
</property>
</enc:encryptor>
</enc:property-placeholder>
<camelContext xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://camel.apache.org/schema/blueprint"
xsi:schemaLocation="http://camel.apache.org/schema/blueprint">
<route>
<from uri="{{uri}}"/>
<log message="logging" loggingLevel="INFO" id="logBeforeService"></log>
</route>
</camelContext>
</blueprint>
EDIT: Response from RedHat Support
So this is a known issue, and theres a couple of Jira issues for it (here and here), and it appears as if the issue has been resolved in newer versions of Camel. I have tested with version 2.12.0.redhat-611412, provided by the patch named jboss-fuse-6.1.0.redhat-379-r1p3, and the exception is no longer being thrown.
Regardless of what I have said previously, im quite happy with this implementation. I would want an exception to be thrown if it couldnt decrypt a value which was actaully encrypted, and that is exactly what happens. I modified the encrypted value to ENC(invalid_and_should_throw_exception), and an exception was thrown exactly like I would expect it to.
Caused by: org.jasypt.exceptions.EncryptionOperationNotPossibleException
EDIT: A more concise Answer
Camel-Blueprint behaves differently to Camel-Core, in regards to the way that it resolves property placeholder values. Camel-Core requires the developer to define a Camel Property Placeholder Resolver, which resolves properties in the Camel Context, for the camel property syntax [1]. Obviously the reasoning behind this is to avoid conflicts between the spring property syntax [2] and the Camel Simple Expression Language syntax [3]. The developer has the choice to optionally bridge the Spring Property Placeholder Resolver with Camel by adding extra configuration.
[1 - Camel Property Syntax]
{{org.my.prop}}
[2 - Spring Property Syntax]
${org.my.prop}
[3 - Simple Expression Language Syntax]
${exchange.body}
In Camel-Blueprint, the bridging between the Blueprint Property Placeholder Resolvers and the Camel Context happens automatically. When a Blueprint Camel Context is created, the Blueprint Bundle Context is injected into it. With the Blueprint Bundle Context, Camel pulls all of the beans out of it and determines if they are assignable to the Apache Aries implementation AbstractPropertyPlaceholder. With each instance of the Property Placeholder Resolvers you have defined, Camel is then capable of calling the resolveProperty method on them, without having to parse the property syntax defined by each of the resolvers.
Because the Jasypt Property Placeholder Resolver expects the placeholder syntax [4], it just ignores everything which dosent match this syntax. Because Camel-Blueprint by-passes that validation which ensures the property syntax, we end up in a scenario where Camel is telling the Jasypt Placeholder Resolver to decrypt every property that we attempt to use in our Camel Context. This of course will throw an exception, because you’re trying to decrypt a property which hasn’t been encrypted.
[4 - Jasypt Blueprint Property Syntax]
ENC(encrypted.value)
Solutions:
Create a class which implements the Jasypt StringEncryptor and holds the StandardPBEStringEncryptor as an attribute. The implemented encrypt and decrypt methods call the encrypt and decrypt methods of the StandardPBEStringEncryptor, but catch any exceptions that are thrown.
This is the solution I gave in my original answer.
This is dangerous, if an encrypted value can’t be decrypted that shouldn’t be ignored. The bundle should not start up, to prevent e.g. your database account from getting locked.
Decrypt values manually before passing them to the Placeholder Resolver.
You could create a configuration service, where you compaile all your configuration from your various sources, decrypt all the encrypted values manually, then expose the properties as an OSGi service to be shared accross bundles.
I’ve gone off this design, it’s basically re-implementing the ConfigurationAdmin service which is provided natively by Karaf (with the addition of decryption which Karaf doesn’t provide), it’s just not as good as the one Karaf provides as it is not capable of detecting when application configuration has changed.
Decrypt values at runtime.
Not a fan of this either, requires your application to be aware of which application properties are expected to be encrypted.
I have raised a support ticket with Redhat through our support contract, I'll keep you updated if anything comes of it.
Original Answer:
I think I figured this one out. According to the camel documentation, in blueprint camel is capable of detecting that a blueprint placeholder resolver is present, and attempts to use that to resolve its properties.
The problem with this is that it does not care what the placeholder prefix and suffix is, it just goes ahead and uses it regarless. The Jasypt placeholder resolver has been desgined so that it is only even invoked if the placeholder prefix is "ENC(" and the suffix is ")", remember Camel dosent care about this. Camel passes its unresolved properties to the Jasypt property resolver, which of course attempts to decrypt them. Because they are not encrypted, an exception is thrown.
To get around this, I have created a custom encryptor which implements the Jasypt StringEncryptor. The custom encryptor contains an instance of the StandardPBEStingEncryptor, and uses that to do the actual encryption/ decryption. The key difference is that Exceptions are caught and ignored, so if an Exception is thrown trying to decrypt a camel property which isnt encrypted, then it is ignored and the application continues as normal.
The Java Class:
package uk.co.test;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CustomEncryptor implements StringEncryptor {
private StandardPBEStringEncryptor encryptor;
private static final Logger LOG = LoggerFactory.getLogger(CustomEncryptor.class);
public CustomEncryptor(String password) {
encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(password);
}
#Override
public String decrypt(String value) {
String ret = null;
try {
ret = encryptor.decrypt(value);
} catch (Exception e) {
LOG.error("Failed to decrypt value.");
}
return ret;
}
#Override
public String encrypt(String value) {
String ret = null;
try {
ret = encryptor.encrypt(value);
} catch (Exception e) {
LOG.error("Failed to encrypt value.");
}
return ret;
}
public StandardPBEStringEncryptor getEncryptor() {
return encryptor;
}
public void setEncryptor(StandardPBEStringEncryptor encryptor) {
this.encryptor = encryptor;
}
}
The Blueprint configuration:
<enc:property-placeholder>
<enc:encryptor class="uk.co.test.CustomEncryptor">
<argument value="myPass" />
</enc:encryptor>
</enc:property-placeholder>

Extracting Salesforce data using Camel throws org.apache.camel.NoTypeConversionAvailableException

I am new to Apache Camel and working on a simple java program that can extract Salesforce custom object data using Apache Camel. While running the program it throws org.apache.camel.NoTypeConversionAvailableException. Objects QueryRecordsLine_Item__c and Line_Item__c implements Serializable interface. Kindly help me to fix this.
Code snippet:
from("direct:query")
.to("salesforce:query?sObjectQuery=SELECT name, Unit_Price__c, Units_sold__c, Merchandise__c, Invoice_Statement__c from Line_Item__c&sObjectClass=" + QueryRecordsLine_Item__c.class.getName())
.to("file:E:\\ajagan\\datafiles\\out");
Exception:
Caused by: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: org.apache.camel.component.salesforce.dto.generated.QueryRecordsLine_Item__c to the required type: java.io.InputStream with value {"done":true,"totalSize":280,"records":[.....]}
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.mandatoryConvertTo(BaseTypeConverterRegistry.java:181)
at org.apache.camel.impl.MessageSupport.getMandatoryBody(MessageSupport.java:99)
... 31 more
You should add camel-jaxb to the classpath, so Camel can covert the salesforce DTO objects (they are JAXB annottated) to XML representation in a stream, that the file endpoint can use.
How about you try converting to a string first:
from("direct:query")
.to(...)
.convertBodyTo(String.class)
.to(...)

Resources