AS400ConnectionPool in Spring - spring

I have a question that can I use AS400ConnectionPool in Spring if then pls provide me the example

Yes, you can... I have never seen that class, but looking at the API this is pretty straithforward:
<bean id="as400ConnectionPool" class="com.ibm.as400.access.AS400ConnectionPool">
<property name="maxConnections" value="128"/>
</bean>
Now you can simply inject the pool into your services:
#Autowired
private AS400ConnectionPool testPool;
//...
AS400 newConn = testPool.getConnection("myAS400", "myUserID", "myPassword", AS400.COMMAND);
It is even easier with Java configuration:
#Configuration
public class As400Config {
#Bean
public AS400ConnectionPool testPool() {
// Create an AS400ConnectionPool.
AS400ConnectionPool testPool = new AS400ConnectionPool();
// Set a maximum of 128 connections to this pool.
testPool.setMaxConnections(128);
// Preconnect 5 connections to the AS400.COMMAND service.
testPool.fill("myAS400", "myUserID", "myPassword", AS400.COMMAND, 5);
return testPool;
}
}
Note that you cannot easily call testPool.fill() in XML configuration.

Related

Spring Integration AOP for Logging outbound Http requests

I was looking at a post from 2014 about using Spring AOP for logging HTTP requests/replies:
Spring integration + logging response time for http adapters(or any endpoint)
To this end, I tried this AOP configuration:
<aop:config >
<aop:aspect id="myAspect" ref="inboundOutboundHttpLogging">
<aop:pointcut id="handleRequestMessageMethod"
expression="execution(* org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleRequestMessage(*))
and
args(message))" />
<aop:before method="requestMessageSent" pointcut-ref="handleRequestMessageMethod" arg-names="message"/>
</aop:aspect>
</aop:config>
Is there perhaps a newer way of using AOP for logging HTTP requests? I want to avoid having to put per-request logging (i.e. outbound-gateway advice on each gateway).
Thanks for any pointers.
The handleRequestMessage() is essentially an input message to this gateway and output. So, if you don't like implementing an AbstractRequestHandlerAdvice and adding it into each your gateway via their <request-handler-advice-chain>, then consider to use a <wire-tap> for input and output channels of those gateway.
You may implement, though, a BeanPostProcessor.postProcessBeforeInitialization() to add your custom AbstractRequestHandlerAdvice into those HTTP gateways you are interested in.
My point is that <aop:aspect> you are presenting us really might lead to some unexpected behavior, like that final method concern you have edit out from your question...
Based upon the suggestions made by #artem-bilan, I was able to find a solution similar to AOP for injecting logging AbstractRequestHandlerAdvice into HTTP outbound request processing. I'm contributing this as a way of showing a possible solution for anyone else who comes across this question.
As #artem-bilan mentions, there is a mechanism for injecting AbstractRequestHandlerAdvice into a AbstractReplyProducingMessageHandler such as an HttpRequestExecutingMessageHandler. In my case, I'm wanting to log the message contents (header and payload) prior to the HTTP call and also log the return message (header and payload). This works nicely.
#artem-bilan suggests that the BeanPostProcessor mechanism can allow to inject the advice without having to add that declaration to each http outbound bean. The BeanPostProcessor looks like this:
public class AddHttpOutboundAdvicePostProcessor implements BeanPostProcessor {
final List<Advice> adviceList;
final AddHttpOutboundAdvicePostProcessor(List<Advice> adviceList) {
this.adviceList = adviceList;
}
#Override
public Object postProcessAfterInitialization(#NonNull Object bean,
#NonNull String beanName)
throws BeansException {
if (bean instanceof AbstractHttpRequestExecutingMessageHandler) {
((AbstractHttpRequestExecutingMessageHandler) bean).setAdviceChain(adviceList);
}
return bean;
}
}
We need to set up this bean into our context. (I'm a die-hard declarative fan hence this is in XML.)
<bean id = "addHttpLoggingPostProcessor"
class = "com.my.package.AddHttpOutboundAdvicePostProcessor" >
<constructor-arg name="adviceList>
<util:list>
<ref bean="outboundLogger" />
</util:list>
</constructor-arg>
</bean>
Here, the outboundLogger is a bean that managers the request-handler-advice. In my choice of implementation, I'm sending a copy of the outbound message to a channel for logging beforehand, and a copy of the response message down another channel for logging the response. The XML declaration of the bean takes the two channel names as constructors:
<bean id="outboundLogger" class="com.my.package.HttpRequestProcessorLogger" >
<constructor-arg name="requestLoggingChannelName" value="XXX" />
<constructor-arg name="responseLoggingChannelName" value="YYY" />
</bean>
where XXX and YYY are the names of channels to the components that perform the logging. I've set these channels to be ExecutorChannels so that the logging is performed asynchronously.
The HttpRequestProcessorLogger bean manages the call to handleRequestMessage():
public class HttpRequestProcessorLogger extends AbstractRequestHandlerAdvice {
private MessageChannel requestLoggingChannel;
private MessageChannel responseLoggingChannel;
private String requestLoggingChannelName;
private String responseLoggingChannelName;
private BeanFactory beanFactory;
public HttpRequestProcessorLogger(String requestLoggingChannelName, String responseLoggingChannelName) {
this.requestLoggingChannelName = requestLoggingChannelName;
this.responseLoggingChannelName = responseLoggingChannelName;
}
#Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
getChannels();
requestLoggingChannel.send(message);
final Object result = callback.execute();
final message<?> outputMessage =
(MessageBuilder.class.isInstance(result) ? ((MessageBuilder<?>) result).build()
: (Message<?>) result;
responseLoggingChannel.send(outputMessage);
return outputMessage;
}
private synchronized void getChannels() {
if (requestLoggingChannelName != null) {
final DestinationResolver<MessageChannel>
channelResolver = ChannelResolverUtils.getChannelResolver(this.beanFactory);
requestLoggingChannel = channelResolver.resolverDestination(requestLoggingChannelName);
responseLoggingChannel = channelResolver.resolverDestination(responseLoggingChannelName);
requestLoggingChannelName = null;
responseLoggingChannelName = null;
}
}
#Override
public void setBeanFactory(#NonNull BeanFactory beanFactory) throws BeanException {
this.beanFactory = beanFactory;
}
}

Proxy database not switching

Spring framework 4.1.4
Spring batch 3.0.2
Tomcat 7
Morning,
I have successfully used a configuration based on Marten Deinum's Post
to dynamically connect (or create and connect) to dbs only known at run time.
The problem I am having is the process now intermittently fails to switch between dbs. The first always works but putting in logging code shows the first properly being created and then the second or third not firing dataSource == null section in the MdyDataSourceFactory - it appears if the process thinks it is the same db and so doesn't change but at some point it triggers and connects to a subsequent db!
Running a simple JUnit test switching between dbs works fine (code correctly fires and dbs switch and select statement returns different id results as expected).
It is being called within a Batch Job step tasklet. The process grabs a count of resultSets (summary table) and connects to the db. For each resultSet it calls the db registry and if exists - returns existing or creates a new one and returns.
My dynamic db xml is:
<bean id="mdyDSRegistry" class="com.k12knowledge.db.MdyDataSourceFactory" />
<bean id="mdyDSTargetSource" class="com.k12knowledge.db.ContextSwappableMdyTargetSource">
<constructor-arg type="java.lang.Class">
<value>javax.sql.DataSource</value>
</constructor-arg>
<property name="targetRegistry" ref="mdyDSRegistry"></property>
</bean>
<bean id="proxyMdyDataSource" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>javax.sql.DataSource</value>
</list>
</property>
<property name="targetSource">
<ref bean="mdyDSTargetSource" />
</property>
</bean>
The MdyDataSourceFactory is:
public class MdyDataSourceFactory implements TargetRegistry {
private ConcurrentMap<String, DataSource> map = new ConcurrentHashMap<String, DataSource>();
#Override
public DataSource getTarget(String context) {
IClientDs client = MdyContextHolder.getClientDs();
Assert.notNull(client, "Client was not set.");
String key = client.getUrl();
DataSource dataSource = map.get(key);
if (dataSource == null) {
System.out.println("dataSource == null - creating new");
dataSource = getDataSource(client);
dataSource = map.putIfAbsent(key, dataSource);
if (dataSource == null) {
// put success
dataSource = map.get(key);
}
}
System.out.println("client key: " + key);
return dataSource;
}
private DataSource getDataSource(IClientDs client) {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(client.getDriver());
dataSource.setUrl(client.getUrl());
dataSource.setUsername(client.getUsername());
dataSource.setPassword(client.getPassword());
dataSource.setValidationQuery("/* ping */");
dataSource.setMaxActive(10);
dataSource.setMaxIdle(5);
dataSource.setTestOnBorrow(true);
dataSource.setTestWhileIdle(true);
dataSource.setRemoveAbandoned(true);
dataSource.setRemoveAbandonedTimeout(20);
dataSource.setTimeBetweenEvictionRunsMillis(34000);
dataSource.setMinEvictableIdleTimeMillis(55000);
try {
System.out.println("dataSource " + client.getUrl() + " closed ? " + dataSource.getConnection().isClosed());
} catch (SQLException e) {
e.printStackTrace();
}
return dataSource;
}
}
At one point I thought there was an issue with the key I used (some databases are only different in name by 1 letter). I then tried adding an UUID to the front of the key to see if that was the issue - no change.
Really puzzled as to why it is not working... Any pointers greatly appreciated.
Thank you for looking.
ContextHolder
public abstract class ContextHolder {
private static final ThreadLocal<IClientDs> holder = new ThreadLocal<IClientDs>();
public static void setClientDs(IClientDs context) {
LoggerFactory.getLogger(ContextHolder.class).debug("context set '{}'", context);
holder.set(context);
}
public static IClientDs getClientDs() {
return (IClientDs) holder.get();
}
}

JMS Rollback & redelivery not honoring the RedeliveryDelay configuration

I would like to have my Camel routes transactional with ActiveMQ. Rollback and maximum re-deliveries work fine, but not re-delivery delay, which should be incremental.
For example, when I failed to process message (raising an exception), it's redelivered 3 times (as expected), but with no time between it (which is not).
My Spring configuration:
<context:annotation-config/>
<context:component-scan base-package="fr.dush.poc.springplaceholder"/>
<spring:camelContext>
<spring:package>fr.dush.poc.springplaceholder.routes</spring:package>
<spring:contextScan/>
</spring:camelContext>
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="jmsTransactionManager"/>
</bean>
<bean id="PROPAGATION_REQUIRES_NEW" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="jmsTransactionManager"/>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
</bean>
Spring configuration continue in configuration bean:
#Component
public class CamelFactories {
private static final Logger LOGGER = LoggerFactory.getLogger(CamelFactories.class);
public static final int REDELIVERY_DELAY = 1000;
public static final int BACK_OFF_MULTIPLIER = 2;
public static final int HOUR = 3600000;
public static final int MAXIMUM_REDELIVERY_DELAY = 2 * HOUR;
public static final int MAXIMUM_REDELIVERIES = 3;
#Bean(name = "jmsConnectionFactory")
public ActiveMQConnectionFactory createFactory() {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
factory.setBrokerURL("tcp://localhost:61616");
RedeliveryPolicy policy = new RedeliveryPolicy() {
#Override
public long getNextRedeliveryDelay(long previousDelay) {
long nextDelay = super.getNextRedeliveryDelay(previousDelay);
LOGGER.warn("Previous delay={} ; This delay={} ", previousDelay, nextDelay);
return nextDelay;
}
};
policy.setMaximumRedeliveries(MAXIMUM_REDELIVERIES);
policy.setRedeliveryDelay(REDELIVERY_DELAY);
policy.setBackOffMultiplier(BACK_OFF_MULTIPLIER);
policy.setUseExponentialBackOff(true);
policy.setMaximumRedeliveryDelay(MAXIMUM_REDELIVERY_DELAY);
factory.setRedeliveryPolicy(policy);
return factory;
}
#Bean(name = "activemq")
public JmsComponent createJmsComponent(JmsTransactionManager transactionManager,
ActiveMQConnectionFactory connectionFactory) {
ActiveMQComponent component = new ActiveMQComponent();
component.setTransactionManager(transactionManager);
component.setConnectionFactory(connectionFactory);
component.setTransacted(true);
return component;
}
My route is quite simple:
public class CamelRouteBuilder extends SpringRouteBuilder {
#Override
public void configure() throws Exception {
Policy required = getApplicationContext().getBean("PROPAGATION_REQUIRED",
SpringTransactionPolicy.class);
from("activemq:queue:foo.bar")
.transacted()
.policy(required)
.log(LoggingLevel.INFO, "fr.dush.poc", "Receive message: ${body}")
.beanRef("serviceBean") // throw an exception
.to("mock:routeEnd");
}
}
And in my logs, I have this, 3 times with previous delay=0:
CamelFactories:36 - Previous delay=0 ; This delay=1000
It seems I'm not alone to have this issue, but I still didn't find solution...
Thanks,
-Dush
This is possibly resolved by setting cacheLevelName=CACHE_CONSUMER on the ActiveMQComponent. I had the same symptoms & this resolved it for me. On a related note, I also get out of order delivery of messages with a transacted component, unless I use CACHE_CONSUMER.
I still didn't find solution. But I found an alternative: retry API from CAMEL itself.
Configuration is very similar. Spring config example:
<redeliveryPolicyProfile id="infiniteRedeliveryPolicy"
asyncDelayedRedelivery="true"
redeliveryDelay="${camel.redelivery_delay}"
maximumRedeliveryDelay="${camel.maximum_redelivery_delay}"
maximumRedeliveries="${camel.infinite_redelivery}"
backOffMultiplier="${camel.back_off_multiplier}"
useExponentialBackOff="true"/>
<routeContext>
<route>
<!-- ... -->
<!-- Define behaviour in case of technical error -->
<onException redeliveryPolicyRef="infiniteRedeliveryPolicy">
<exception>java.lang.Exception</exception>
<handled>
<constant>false</constant>
</handled>
<log message="Message can't be processed for now. I'll retry later!" />
</onException>
</route>
</routeContext>
Consumers should be transactional if you want to keep not processed messages in the ActiveMQ queue, even if you shut down application.

Connect LDAP from Spring

I have to realize a web application based on Spring, allowing the user to manage LDAP data. The connection to the LDAP should be done only with the JNDI framework (no SpringLDAP allowed).
For this, I realized a utility class to do the basic operations (add, update, delete, list, ...).
Here is a short block of code of this class :
public class LdapUtility {
private static LdapUtility instance;
private DirContext dirContext;
public static LdapUtility getInstance() {
if(LdapUtility.instance == null)
LdapUtility.instance = new LdapUtility();
return LdapUtility.instance;
}
/**
* Connect to the LDAP
*/
private LdapUtility() {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=Manager,dc=my-domain,dc=com");
env.put(Context.SECURITY_CREDENTIALS, "secret");
try {
dirContext = new InitialDirContext(env);
}
catch(Exception ex) {
dirContext = null;
}
}
public void addUser(User u) {
dirContext.createSubcontext(....); //add user in the LDAP
}
}
With this code, I can access all my methods by calling LdapUtility.getInstance()..., but the connection to the LDAP will never be released.
Another way would be to connect to the LDAP before each operation, but in this case there would be too much connections to the LDAP...
So, here is my question : what is the most elegant/smartest way to access these methods ?
Thank you in advance :-)
Since you're already using Spring, I would recommend using Spring LDAP:
Spring LDAP is a Java library for simplifying LDAP operations, based on the pattern of Spring's JdbcTemplate. The framework relieves the user of common chores, such as looking up and closing contexts, looping through results, encoding/decoding values and filters, and more.
Especially if you're not familiar with LDAP and potential performance problems, it can help to start of using a utility library like this that will do all the heavy lifting for you.
You configure the LDAP connection settings in the spring config:
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://localhost:389" />
<property name="base" value="dc=example,dc=com" />
<property name="userDn" value="cn=Manager" />
<property name="password" value="secret" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
You can then just use the LdapTemplate wherever you need to perform an LDAP action:
return ldapTemplate.search(
"", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
without a spring (being forbidden), i would quickly implement something simillar:
(when being lazy) create a simple callback interface (such as you can find in spring -- JpaCallback.execute(EntityManager em)) -- but for LDAP -- MyLdapCallback.execute(LdapConnection connection) -- intead of LdapConnection you can imagine anything you require -- objects from OpenLdap or SDK Context. Something like (just for presentation):
...
interface LdapCallback<T> {
T execute(DirContext ctx) throws NamingException, IOException;
}
...
private <T> T execute(LdapCallback<T> callback) throws NamingException, IOException {
T result = null;
LdapContext ctx = new InitialLdapContext();
try {
result = callback.execute(ctx);
} finally {
if (tls != null) {
tls.close();
}
ctx.close();
}
return result;
}
...
Once done, you will create anonymous classes for each Ldap call an call the callback via execute(callback).
(having more time) implement ad 1. + create AOP that will wrap my methods marked with annotation with aspect that will itself execute my methods within the wrapper above (without explicitly doing so in my code)
There are several ways to connect to ldap. Using javax.naming.* is one of them. In javadoc you may find, that classes in your SPI provider manages their own connections, so you don't care for it -- that may be an answer to your question -- see JDK doc and how Context manages conections and network -- http://docs.oracle.com/javase/6/docs/api/javax/naming/ldap/LdapContext.html .
If you are accustomed to more JDBC-like access, you may find http://www.openldap.org/jldap/ more to your liking. There you have conections completely under your control and you treat them much the same way as in JDBC. You may use any pooling library you like.
Not knowing the exact requirements I interpret the core question as being "when to open/close the connection".
My crystal ball tells me you may want to use a connection pool. True, you don't close the connection explicitly as this is handled by the pool but this may be ok for your assignment. It's fairly easy:
// Enable connection pooling
env.put("com.sun.jndi.ldap.connect.pool", "true");
The complete source code is referenced in Oracle's basic LDAP tutorial.

Spring integration: difficulty with transaction between 2 activators

I have this use case.
First chain:
<int:chain input-channel="inserimentoCanaleActivate" output-channel="inserimentoCanalePreRouting">
<int:service-activator ref="inserimentoCanaleActivator" method="activate" />
</int:chain>
This is the relative code:
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public EventMessage<ModificaOperativitaRapporto> activate(EventMessage<InserimentoCanale> eventMessage) {
...
// some Database changes
dao.save(myObject);
}
All is working great.
Then I have another chain:
<int:chain id="onlineCensimentoClienteChain" input-channel="ONLINE_CENSIMENTO_CLIENTE" output-channel="inserimentoCanaleActivate">
<int:service-activator ref="onlineCensimentoClienteActivator" method="activate" />
<int:splitter expression="payload.getPayload().getCanali()" />
</int:chain>
And the relative activator:
#Override
public EventMessage<CensimentoCliente> activate(EventMessage<CensimentoCliente> eventMessage) {
...
// some Database changes
dao.save(myObject);
}
The CensimentoCliente payload as described below has a List of payload of the first chain, so with a splitter I split on the list and reuse the code of the first chain.
public interface CensimentoCliente extends Serializable {
Collection<? extends InserimentoCanale> getCanali();
void setCanali(Collection<? extends InserimentoCanale> canali);
...
}
But since every activator gets his transaction definition (since the first one can live without the second one) I have a use case where the transactions are separated.
The goal is to have the db modifies of the two chains been part of the same transaction.
Any help?
Kind regards
Massimo
You can accomplish this by creating a custom channel (or other custom component, but this is the simplest approach) that wraps the message dispatch in a TransactionTemplate callback execution:
public class TransactionalChannel extends AbstractSubscribableChannel {
private final MessageDispatcher dispatcher = new UnicastingDispatcher();
private final TransactionTemplate transactionTemplate;
TransactionalChannel(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
#Override
protected boolean doSend(final Message<?> message, long timeout) {
return transactionTemplate.execute(new TransactionCallback<Boolean>() {
#Override
public Boolean doInTransaction(TransactionStatus status) {
return getDispatcher().dispatch(message);
}
});
}
#Override
protected MessageDispatcher getDispatcher() {
return dispatcher;
}
}
In your XML, you can define your channel and transaction template and reference your custom channel just as you would any other channel:
<bean id="transactionalChannel" class="com.stackoverflow.TransactionalChannel">
<constructor-arg>
<bean class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
<property name="propagationBehavior" value="#{T(org.springframework.transaction.TransactionDefinition).PROPAGATION_REQUIRES_NEW}"/>
</bean>
</constructor-arg>
</bean>
For your example, you could perhaps use a bridge to pass the message through the new channel:
<int:bridge input-channel="inserimentoCanaleActivate" output-channel="transactionalChannel" />
<int:chain input-channel="transactionalChannel" output-channel="inserimentoCanalePreRouting">
<int:service-activator ref="inserimentoCanaleActivator" method="activate" />
</int:chain>
You you have <service-activator> and #Transactional on service method, the transaction will be bounded only to that method invocation.
If you want to have a transction for entire message flow (or its part) you should declare TX advice somewhere before.
If your channels are direct all service invocations will be wrapped with the same transaction.
The most simple way to accomplish your wishes, write simple #Gateway interface with #Transactional and call it from the start of your message flow.
To clarify a bit regarding transactions
Understanding Transactions in Message flows
Are these modifying 2 separate relational databases ? If so you are looking at an XA transaction. Now if you are running this on a non XA container like tomcat, all of this must be done in a single thread that is watched by a transaction manager - (you will have to piggy back on the transaction manager that actually triggers these events). The transaction manager can be a JMS message or a poller against some data source. Also this processing must be done in a single thread so that spring can help you run the entire process in a single transaction.
As a final note , do not introduce threadpools / queues between service activators. This can cause the activators to run in separate threads

Resources