Wednesday, April 30, 2014

Spring-Integration Resolve Error: one of inputChannelName or inputChannel is required

I have encountered one time this kind of error while deploying my  Web application based on Spring-Integration. The error were:

Caused by: java.lang.IllegalStateException: one of inputChannelName or inputChannel is required
at org.springframework.util.Assert.state(Assert.java:385) [spring-core-4.0.3.RELEASE.jar:4.0.3.RELEASE]
at org.springframework.integration.config.ConsumerEndpointFactoryBean.initializeEndpoint(ConsumerEndpointFactoryBean.java:225) [spring-integration-core-4.0.0.M4.jar:]


In fact, I was managing errorChannel and my Service Activator responsible of handling the error messages was declared like this :


1
2
3
4
5
6
7
8
<int:channel id="errorChannel"/>

<int:service-activator id="errorHandler"
 input-channel="errorChannel" 
 method="handleError" 
 output-channel="nullChannel" 
 ref="errorHandler"/>
  

Although my input channel is declared, I get the error.
The problem was that I put the same name for the id and ref in the service-activator. So the error is caused by that and not because the input channel is not declared. So I have rectified my code :



1
2
3
4
5
6
7
8
<int:channel id="errorChannel"/>

<int:service-activator id="errorService"
   input-channel="errorChannel" 
   method="handleError" 
   output-channel="nullChannel" 
   ref="errorHandler"/>
  

Monday, April 28, 2014

Resolved : Spring Initialize a bean which depends on another bean: Use JdbcTemplate when initializing a bean.

I was working on a web project using spring. I needed in the project to initialize a cache by doing a call to the database. So in order to do so, I was putting the database call in the default class constructor.
So in my Configuration class I do

@Bean("usersCache")
@DependsOn("myJdbcTemplate")
public UsersCache userCache{
    return new UsersCache(); 
}

And in the UserCache constructor I do :

@ManagedResource
public class UsersCache {
@Autowired
JdbcTemplate jdbcTemplate;

@PostConstruct
public UsersCache(){

@SuppressWarnings({ "unchecked", "rawtypes" })
List<LatestRecordPerUser> latestRecordByDevice = jdbcTemplate.query(populateCache, new BeanPropertyRowMapper(LatestRecordPerUser.class));
for(LatestRecordPerUser record:latestRecordByDevice ){
// And Here I insert into my cache
}
}


But even using this code I get a NullPointerException as the JdbcTemplate bean is not injected:

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [main.java.org.beans.UsersCache ]: Constructor threw exception; nested exception is java.lang.NullPointerException

I have later understand that as the UsersCache is not yet initialized, nothing will be injected to it. So only after initialization, spring will inject the jdbcTemplate and thus we can execute the request.

So the fix the problem, there is no need to use @dependsOn . We need just to populate the cache after the bean (or repository) initialisation, So this can be done thanks to @PostConstruct. So the code is now :

@Repository
@Scope("singleton")
public class UsersCache {
@Autowired
JdbcTemplate jdbcTemplate;

private final Map userCache = new ConcurrentHashMap();

@PostConstruct
public void init(){

@SuppressWarnings({ "unchecked", "rawtypes" })
List<LatestRecordPerUser> latestRecordByDevice = jdbcTemplate.query(populateCache, new BeanPropertyRowMapper(LatestRecordPerUser.class));

for(LatestRecordPerUser record:latestRecordByDevice ){
// And Here I insert into my cache
}
}

Thant's it :D

Saturday, April 26, 2014

Resolve TransactionManager lookup fails on JBoss EAP 6 (AS7): No JTA TransactionManager found at fallback JNDI location (NameNotFoundException)

Using JBoss EAP 6.2, I have an application running on it. I needed to exclude the JBoss Logging as explained in this link.
So adding the exclusion in the jboss-deployment-structure.xml I have errors.

 javax.naming.NameNotFoundException: TransactionManager -- service jboss.naming.context.java.module.myprojectname.TransactionManager
org.springframework.transaction.jta.JtaTransactionManager] No JTA TransactionManager found at fallback JNDI location [java:appserver/TransactionManager]
 javax.naming.NameNotFoundException: java:appserver/TransactionManager
javax.naming.NameNotFoundException: java:pm/TransactionManager

Oh oOh what happens. Ayyy. Jboss is angry because I have excluded its logging :|. Ok I will not use the Jboss logging even if it is not happy for that.
So now I need to fix the jndi lookup of the jboss transaction manager. If you look in Standalone.xml, you will not find this jndi name. Strange no !! In fact by default it is java:jboss/TransactionManager.

So all what I need now is to specify to Spring the name of my Transaction Manager. So first, I have removed the old declaration :


<tx:jta-transaction-manager/>

And I substitute it by : 


1
2
3
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
       <property name="transactionManagerName" value="java:jboss/TransactionManager"/>
</bean>

And now every think is working and I can see in the log while deploying :

DEBUG org.springframework.transaction.jta.JtaTransactionManager  - Retrieving JTA TransactionManager from JNDI location [java:jboss/TransactionManager]

Thursday, April 24, 2014

Resolved : log4j:WARN No appenders could be found for logger (org.springframework.web.context.support.SpringBeanAutowiringSupport

I was fixing my Log4j.xml on my web project developed with Spring and running on JBoss.


Deploying my application, It catches my eyes an error message although my application was deployed.
it was this error:

4:27:14,323 ERROR [stderr] (MSC service thread 1-2) log4j:WARN No appenders could be found for logger (org.springframework.web.context.support.SpringBeanAutowiringSupport).
14:27:14,323 ERROR [stderr] (MSC service thread 1-2) log4j:WARN Please initialize the log4j system properly.

It was really strange as I declare a logger for org.springframework.
But it seems that the porblem is coming from SpringBeanAutowiringSupport. Although I have declared also a logger fro this method. It didn't work and I get the same error.

What is special for this class is that I am using it to extend my web service class an that it will be initialized and managed by Spring.
So my code was like this :

@WebService(serviceName = "UserService")
public class UserService extends SpringBeanAutowiringSupport {
// Here the service implementation
...
}

It was a normal code. And it works fine. But my log4j seems not very happy.
After some search, I have seen by chance in one blog how to use the SpringBeanAutowiringSupport differently.
Based on that, I have modified my code and now it looks like this :

@WebService(serviceName = "UserService")
public class UserService extends SpringBeanAutowiringSupport {

   @PostConstruct
    public void init() {
              SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

...
}

Surprise, now every think is working nice and I have no more error messages while deploying.  This is nice :D

Surprise, When testing the Web service. I have a NullPointerException. So now I know that the Error comes from the extends. But to make my web service work, I need to use it.

Monday, April 21, 2014

Resolve Error: org/springframework/cglib/transform/impl/MemorySafeUndeclaredThrowableStrategy

I was working on a web application using Spring application.

When deploying my application on JBoss eap 6.2 Server, I got this Error :

Caused by: java.lang.NoClassDefFoundError: org/springframework/cglib/transform/impl/MemorySafeUndeclaredThrowableStrategy
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:187) [spring-aop-3.2.8.RELEASE.jar:3.2.8.RELEASE]
...
Caused by: java.lang.ClassNotFoundException: org.springframework.cglib.transform.impl.MemorySafeUndeclaredThrowableStrategy from [Module "deployment.dbm.war:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:197) [jboss-modules.jar:1.3.0.Final-redhat-2]

It was strange as I was using Spring Integration 3.0.2.RLEASE.

<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version> 3.0.2.RELEASE</version>
</dependency>

As I have then used the 4.0.0.M4 version of Spring-Integration. So I have decided to use it and once updated the web application was deploying with success.

<repositories>
<repository>
<id>spring-milestones</id>
<url>http://repo.springsource.org/libs-milestone/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>4.0.0.M4</version>
</dependency>

Sunday, April 20, 2014

Resolved : log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader)

I was using log4j in one of my spring maven projects. although the log4j.xml were well done, I get a warning then an error during deployment :

Initializing Spring root WebApplicationContext
 [stderr] (ServerService Thread Pool -- 74) log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
 ERROR [stderr] (ServerService Thread Pool -- 74) log4j:WARN Please initialize the log4j system properly.
 ERROR [stderr] (ServerService Thread Pool -- 74) log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

My log4j.xml was under src/main/resources. bUT EVEN BY SPECIFYING THE log4jConfigLocation, didn't resolve the problem.
So my Web.xml were like this:





After some invetigation, I have found that we should add a Log4jConfigListener in the first line (with the log4jConfigLocation) :

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

So the Web.xml become:





Wasn't easy to find but at least now it is done :)

Thursday, April 17, 2014

Resolving Bash Error: syntax error near unexpected token `(' declare -a

Writing a bash script, I got an error when trying to run it :

syntax error near unexpected token `(' declare -a

My array was declared was :
declare -a persons = ('person1' 'person2')

Even though my code looks correct and nice ;) ,  Unix don't accept it. I was removing the quotes.... but nothing worked.

And finally I find the solution: In fact we shouldn't put any space between = and (.

declare -a persons=('person1' 'person2') 

Monday, April 14, 2014

Spring Integration: Mqtt integration and Transformation of the mqtt Message from CSV to Java Bean using int:transformer


Working with Spring Integration, the use of Mqtt become very easy. In fact we need only to declare an int-mqtt:message-driven-channel-adapter in the applicationContext or spring-integration-context.xml

The code is :



The integration graph looks then like this :

So in order to convert the message coming from the broker (in CSV format), we need to call the method convert in the created CsvConverter class. In order to configure this using int:transformer, we need to declare a spel-function where we specify the class and called method, then we use the Id inside the spEL expression inside the transformer by putting # before the id of the converter.
so here is the code.

<int:spel-function id="csvConverter" class="org.converter.CsvConverter" method="convert(java.lang.String)" />

<int:transformer id="csvTransformer"
input-channel="mqttMessages"
output-channel="record" expression="#csvConverter(payload)" />

So now the transformer will call the CSVConverter which will convert the mqtt message payload from CSV to Java Bean (here Record).  The conversion is done using CSVeed framework which construct the given bean from the csv message.




Spring integration Channel Queue Get the current queue size (queue monitoring)

Using Spring-integration (version 4.0.0.M4), I was using a channel Queue where I Put Mqtt Messages. Multi-threads will take messages from that queue in order to process them.
I needed to know the size of the Queue and to Log it. Warning may be logger if the Queue is reaching some threshold.

So my code look like this:
In the spring-integration.xml  (or applicationcontext.xml), I have declared my channel having a Queue.


No in my Code, I use :

@Qualifier(value="mqttMessages")
@Autowired(required=false)
QueueChannel  queue;

So I get the channel by its Id. So now I can get the Channel Queue Size using :
queue.getQueueSize()

Sunday, April 13, 2014

Spring JdbcTemplate/ NamedJdbcTemplate tutorial : Resolve Date insertion

I was working with Spring JdbcTemplate to insert rows in the data base. My query is:
insert into person (person_id, name, birth_date) values(?, ?, ?)

@Autowired
JdbcTemplate jdbcTemplate;
private String query ="insert into person (person_id, name, birth_date) values(?, ?, ?)"

public void store(Person person){

       jdbcTemplate.update(query , person.getId(), person.getName(), person.getBirthDate());

}

Using this code, I get this error

 org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [insert into
...]
; nested exception is org.postgresql.util.PSQLException: ERROR: column "birth_date" is of type timestamp with time zone but expression is of type character varying

So the database is not accepting the java.util.Date.
Next olution is to use the DATE '2004-02-02' of postgres, so I have modified my query:
insert into person (person_id, name, birth_date) values(?, ?, DATE ?)

So even with this modification I got :
nested exception is org.postgresql.util.PSQLException: ERROR: syntax error at or near "$3"

Ok, so maybe I need to add qotes. My query is now :
insert into person (person_id, name, birth_date) values(?, ?, DATE '?')
This didn't resolve the problem and I got this error:
PSQLException: The column index is out of range: 3, number of columns: 2

Ok, so my last chance is to use NamedParameterJdbcTemplate.
I have modified my code:
1- In the aplicationContext, I added:

<bean id="namedJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate" >
        <constructor-arg ref="myDataSource" />
</bean>

2- In my code :

@Autowired
protected NamedParameterJdbcTemplate namedJdbcTemplate;

        private String query ="insert into person (person_id, name, birth_date) values(:id, :name, :birthDate)";

public void store(Person person){

       MapSqlParameterSource params = new MapSqlParameterSource();
   params.addValue("id", person.getId());
       params.addValue("name",  person.getName());
       params.addValue("birthDate", person.getBirthDate(), Types.DATE);
       jdbcTemplate.update(query , params);

}

Adding the Types.DATE ( don't forget to import java.sql.Types;), has resolved the problem, and now the insertion is working without any ProBleM ;)


Sunday, April 6, 2014

CSV Tutorial : Convert CSV to Java Bean

In my project I needed to convert a CSV file to a list of beans (Person).
I first used JSEFA, but once tested, I have discovered that this framework have problem to convert fields to Double or Float.

I decided then to move to another framework, and finally I found the CSVeed framework which is quit nice and simple.



By default, the separator in CSVeed is ";" so make sure to change it if necessary.

@CsvFile(comment = '%', quote='\'', escape='\\', separator=',')
public Class Person{
...
}

Their web site have a comparison  with other frameworks which do also the conversion. For more details, have a look on their matrix.

Thursday, April 3, 2014

Spring-integration-mqtt development and resolve MessageDispatchingException Dispatcher has no subscribers

I was using Spring-Integration-Mqtt in order to get messages from the mqtt Broker.


 

But while testing my application, I got this exception:

 org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:107) [spring-integration-core-4.0.0.M4.jar:]
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97) [spring-integration-core-4.0.0.M4.jar:]
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) [spring-integration-core-4.0.0.M4.jar:]
... 10 more

Although the sent messages were received, I got the error. After some investigation, I have found that the problem don't come from spring-mqtt but from my side.
In fact by error, I have declared the service-activator and another bean  with the same Id.

So, If you have this error, make sure that your integration.xml (or applicationContext.xml) is correct.

Now, in order to take benefit from mqtt using Spring, you need to use spring-integration-mqtt and just configure few lines.

The Pom looks like this (if you have problem to locate the remote repository, see this post) :





And the intergration.xml:



Wednesday, April 2, 2014

Setup Maven to access non local repository

I was using Maven in my project, and I needed to add Spring Integration dependency but this latest have its own repository.



But Maven was complaining as it is not considering the given repository and it didn't find the library in the Local repository.
So thanks to a friend (AbdullaF), the solution was to  make some change in the maven setting file.
So just need to go to the local repository (for me it is "C:\.m2"). Then edit the setting.xml.

search for mirrorOf and change it from * to central. Like this Maven will consider the repositories that you specify in the pom.xml.


Tuesday, April 1, 2014

Install and Deploy applications remotely with JBoss eap 6 (JBoss AS7)

This time I will show you how to install, deploy and Test an application remotely on JBoss EAP 6.2, few steps should be done:

Step1: Install JBoss on the remote server.

In order to do that, you need FileZilla and Putty (to execute commands).
So first connect to the remote server using FileZilla. You can put directly your installed JBoss on the remote server or install a new one. Here I will not copy my working one, but I will take the second choice.
So I download the JBoss EAP 6 jar and transfer it to the server.


Then using Putty connect also the server (using an admin account).
Once connected execute these commandes:
java -version
At least you need the version 1.6 of Java.

mvn --version
At leat you need version 3.0

unzip jboss-eap.6.x.x.jar

JBoss will be then installed. So next run it. To do so go to jboss-eap.6.x/bin folder then execute ./standalone.sh. Your server should run without error.

In order to access the console, you need to create a client accout. So using putty and being in the bin folder, execute the command ./addUser.sh.  Then follow the instructions (I used the managementRealm). This account will be used in the console.


Step2: Configure you JBoss.

Now, if you have added some modules to your server like jdbc, or dataSource definition don't forget to add them. So using FileZilla, you can add the new module. For me it was "C:\jboss-eap-6.2\modules\system\layers\base\org\postgresql".
Don't forget also to configure the Standalone.xml with your DataSource and especially give the address where you dataBase is running (my dataBase is running on the same server).

Step3: Configure Remote access to the Console and Web Services.

By default, JBoss can be accessed only locally using the address 127.0.0.1. So I wasn't able to access the console neither the webservices (once the application deployed, coming below).
To fix that, we need to make some changes in the "jboss-eap-6.2/standalone/configuration/standalone.xml" where I change the IP addresses from 127.0.0.1 to 0.0.0.0. Like this, JBoss will accept remote call to the Console and to the Web Services.

In order to make it easy to edit remote files, configure FileZilla to edit your files using your favorite program. So in FileZilla go to Edit->Settings and choose you program.


Then:
Come back to Standalone.xml, it should look like this:

So all the addresses are 0.0.0.0.

Step4: Generate the war.


Before deploying the application, you should first generate the war. This cone be done using ant, or using eclipse. So right clic on the project, and Export.


Choose where to save this war locally.

Step5: Deploy the application

It is time to deploy the application. In order to do that (using the console). So use the adress (put your server address instead of "remoteServerAddress"): 
http://remoteServerAddress:9990/console.
Once connected, go to ManageDeployment section. You need to specify your war location. 


Once added, clic on En/Disable in order to enable it and deploy it on the server.


Now you application is ready to be tested.

Step6: Test the application

As my application is a Web service, I need only the address of the WSDL wich I will put in SoapUI. So clic on the deployed war -> webservices and you will have details about the WSDL...
Just create a new project in SoapUI and specify the address of the WSDL.


That's all for today, I hope really that it helped you :)

Articles les plus consultés