Spring XD Java config doesn't load xml resource - spring-xd

I am using Spring XD to create stream twittersearch then wired to my tweet-processor then wired to log.
I used Java config class all fine no issues, then I wanted to add applicationContext.xml in my ModuleConfiguration class using #ImportResource
#Configuration
#ImportResource("config/applicationContext.xml")
#EnableIntegration
public class ModuleConfiguration {
#Bean
MessageChannel input() {
return new DirectChannel();
}
#Bean
MessageChannel output() {
return new DirectChannel();
}
#Autowired
TweetProcessor tweetProcessor;
#Bean
freemarker.template.Configuration configuration() {
return new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_23);
}
}
And the applicationContext.xml content:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:/apps/conf/application.properties</value>
</list>
</property>
</bean>
</beans>
And my stream definition: stream create --name JustCreate --definition "twittersearch --query=Java | tweet-processor | log" --deploy
When the stream deployed I got error:
2015-10-21T11:26:26+0800 1.2.1.RELEASE WARN twitterSource-1-1 twitter.TwitterSearchChannelAdapter - Exception while reading stream.
org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'singlenode:default,admin,singlenode,hsqldbServer:9393.JustCreate.0'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
I have tried also using spring-module.xml approach (not using Java config at all) and that approach works.
But I am just curious whether Spring XD Java config not supporting #ImportResource annotation.
Thanks.

Spring XD creates an application context in the normal normal way from an XML or #Configuration class once it locates and resolves the configuration resources. XD looks in the config directory. If it finds a .xml or or .groovy file, it will use that file to create the application context. If not, it will look for a .properties file and a base_packages property to scan for #Configuration classes. Since you have an XML file in the config directory, the #Configuration is being ignored. To import resources put them in a different path. This can be a sub-directory of config or a different top level directory. This is discussed in detail in the Modules section of the XD reference guide.

Related

Property placeholders with YamlPropertiesFactoryBean and Spring Boot

I am migrating a small "legacy" application to Spring Boot and ran into an issue with property placeholders in combination with a YamlPropertiesFactoryBean. The application uses Spring XML configuration.
I added a Spring Boot "main" to the project like so:
#SpringBootApplication
#ImportResource("classpath:spring-config.xml")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
I have placed an application.yaml into /config. It is being picked up by Spring boot and I can access properties defined in it via property replacement (${some.prop}) in bean declarations in the imported spring-config.xml. E.g.
<bean id="myRouteBuilder" class="org.camelSpringBoot.test.MyRouteBuilder">
<property name="someProp" value="${prop.from.application.yaml}"/>
</bean>
Except when using a org.springframework.beans.factory.config.YamlPropertiesFactoryBean to read an additional, external configuration file: A property for the file location in the constructor arg of a org.springframework.core.io.FileSystemResource does not get resolved:
<bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
<property name="resources">
<list>
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg value="${service.config.loc}" />
</bean>
</list>
</property>
</bean>
yields
java.io.FileNotFoundException: ${service.config.loc}
If I hard-code the location of the external configuration then properties used in the external YAML file are not resolved either.
application.yaml:
security:
keystore:
loc: /security/my.keystore
external config:
services:
a:
ssl:
secret: ${security.keystore.loc}
java.lang.RuntimeException: Cannot open keystore/truststore ${security.keystore.loc}
Note that the error complains about the verbatim property.
The YamlPropertiesFactoryBean instance is declared in spring-config.xml like the other beans that successfully use property placeholders (meaning properties get replaced by their values). Why would it fail for the YamlPropertiesFactoryBean
Is it possible to enable placeholder resolution for the external YAML document?
I do not know if it is working what you are trying to do. The Property resolving takes place after a BeanDefinition is done, and therefore only working with Spring Beans, but not arbitrary files like your yaml file.
Most build tools (gradle, maven) contain a functionality to resolve those placeholder during build time. Might that be a solution for you?

Issues while running JUnit on maven project using Spring JTA

I have a Spring + Hibernate project deployed on JBoss 5. It was using Ant earlier and recently I have modified the project structure to use Maven 2. But all the code and config files are the same.
I am using Spring JTA for transaction management in my project. I am able to perfecly buid the project and deploy it on JBoss. But when I try to execute the JUnit tests it gives me the following error:
java.lang.IllegalStateException: No JTA UserTransaction available - specify either 'userTransaction' or 'userTransactionName' or 'transactionManager' or 'transactionManagerName'
at org.springframework.transaction.jta.JtaTransactionManager.checkUserTransactionAndTransactionManager(JtaTransactionManager.java:473)
at org.springframework.transaction.jta.JtaTransactionManager.afterPropertiesSet(JtaTransactionManager.java:413)
The wierd thing is that this was working perfeclty fine when I was using Ant. It started coming after the migration to maven.
This is the entry in spring-jpa-conf.xml file:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" >
</bean>
And this is the Junit code:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:spring-conf.xml" })
#Transactional(value = "transactionManager")
public abstract class LocalUsersTestBase {
#PersistenceContext(unitName="books-lemf")
protected EntityManager entityManager;
protected void getUsersDetails(List<Users> out) {
..........
}
I also tried to add a property in the config file entry as shown here:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" >
<property name="userTransactionName" value="java:/TransactionManager"></property>
</bean>
But it gives the error:
Caused by: org.springframework.transaction.TransactionSystemException: JTA UserTransaction is not available at JNDI location [java:/TransactionManager]; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at org.springframework.transaction.jta.JtaTransactionManager.lookupUserTransaction(JtaTransactionManager.java:548)
at org.springframework.transaction.jta.JtaTransactionManager.initUserTransactionAndTransactionManager(JtaTransactionManager.java:425)
at org.springframework.transaction.jta.JtaTransactionManager.afterPropertiesSet(JtaTransactionManager.java:412)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1460)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1400)
... 37 more
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
Please help.
Thanks!!
This is my complete spring config file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" >
</bean>
<jee:jndi-lookup id="books-pu"
jndi-name="java:/books-emf"
cache="true"
lookup-on-startup="false"
proxy-interface="javax.persistence.EntityManagerFactory"
/>
<jee:jndi-lookup id="booksDataSource" jndi-name="java:/books-ds"/>
</beans>
Firsty, from spring reference documentation
If you use JTA in a Java EE container then you use a container
DataSource
, obtained through JNDI,
in conjunction with Spring’s
JtaTransactionManager
. This is what the JTA and JNDI lookup version
would look like:
The
JtaTransactionManager
does not need to know about the
DataSource
, or any other specific
resources, because it uses the container’s global transaction management infrastructure
then when you run the tests you need to a environment container managed to get a JTA User Transaction. In addition can you share with us the complete spring configuration

NoSuchMethodError in Jetty with Spring Data Mongo custom repository

I have a small web application in development using Maven, Spring MVC and Spring Data Mongo. I am getting a java.lang.NoSuchMethodError when one of my Controllers attempts to access a method defined in a custom repository. The same method works fine when exercised via a JUnit 4 test extending AbstractJUnit4SpringContextTests and using a near-identical XML configuration file.
Standard repository:
public interface IndividualRepository extends MongoRepository<Individual, String>, IndividualRepositoryCustom {
...
}
Custom interface:
public interface IndividualRepositoryCustom {
Individual findByIdentifier(String identifierType, String identifierValue);
}
Custom implementation:
public class IndividualRepositoryImpl implements IndividualRepositoryCustom {
#Autowired
private MongoTemplate mongoTemplate;
#Override
public Individual findByIdentifier(String identifierType, String identifierValue) {
String locator = String.format("identifiers.%s", identifierType);
return mongoTemplate.findOne(query(where(locator).is(identifierValue)), Individual.class);
}
}
dataaccess-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<mongo:repositories base-package="com.myco.dataaccess"/>
<mongo:mongo host="mongo.myco.com" port="27017"/>
<mongo:db-factory dbname="test" mongo-ref="mongo"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongo"/>
<constructor-arg value="test"/>
</bean>
</beans>
In my JUnit test I have (excerpt):
#Autowired
private IndividualRepository individualRepo;
...
List<Individual> foundList = individualRepo.findAll();
assertNotNull(foundList);
assertTrue(foundList.size() > 0);
Individual found = individualRepo.findByIdentifier("someid", "123456");
assertNotNull(found);
assertEquals("Bob", found.getFirstName());
The test passes fine, calling both findAll() (standard Repository method) and findByIdentifier() (custom method). The latter fails with NoSuchMethodError when called by a Controller running in a web application in Jetty, while the same Controller can call findAll() with no issues.
This turned out to be nothing to do with Spring Data, but an issue with the way I was using the maven-jetty-plugin with my multi-module build.
Basically, I was running mvn jetty:run for my web module which had a dependency on my dataaccess module (where my JUnit tests lived). As I was rebuilding the project with mvn clean package, the latest versions were not being placed in my local repo, and therefore were not being picked up by the mvn jetty:run process running alongside my build process. Problem was solved by building with mvn clean install.
So, as usual, the error message was spot on - the method indeed did not exist in the version of the JAR that Jetty was being supplied.

Working example on Spring Mediator in WSO2 ESB 4.6.0

Hi i am working on Spring Mediator in WSO2 ESB 4.6.0, using this and this tutorial
I am getting the Error as follows:
ERROR - SpringMediator Cannot look up Spring configuration conf/sample/resources/spring/springsample.xml
ERROR - SpringMediatorCannot reference application context with key : conf/sample/resources/spring/springsample.xml
Could you please explain me how to solve this.
I got to work this as below,
The class should extends AbstractMediator and override the mediate() method as follows,
package com.test.spring.mediator.workingexampleonspringmediator;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
public class HelloWorld extends AbstractMediator{
private String message;
public void setMessage(String message){
this.message = message;
}
public boolean mediate(MessageContext arg0) {
System.out.println("HELLO "+message);
return true;
}
}
Then place the jar in [ESBHOME]/repository/components/lib folder
In mediate method it prints a message with the argument like HELLO 'arg'
And I added the following file to registry (/_system/config/repository/spring/springtest.xml),
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="springtest" class="com.test.spring.mediator.workingexampleonspringmediator.HelloWorld" singleton="false">
<property name="message"><value>ISURU</value></property>
</bean>
</beans>
My proxy is as follows,
<proxy xmlns="http://ws.apache.org/ns/synapse" name="testSpring" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<log level="full">
<property name="START" value="__________________________"/>
</log>
<spring:spring xmlns:spring="http://ws.apache.org/ns/synapse" bean="springtest" key="conf:/repository/spring/springtest.xml"/>
<log level="full">
<property name="END" value="______________________"/>
</log>
</inSequence>
</target>
<description></description>
</proxy>
In the proxy you can see the bean=[bean id of the springtest.xml] and class=qualified name of the class
In my ESB terminal, I got the following out put with the given property value in springtest.xml,
[2013-11-07 17:38:30,654] INFO - LogMediator To: /services/testSpring.testSpringHttpSoap12Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:bcae82e9-4027-43c5-bd7a-cbfa885aaf33, Direction: request, START = __________________________, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body/></soapenv:Envelope>
HELLO ISURU
[2013-11-07 17:38:30,692] INFO - LogMediator To: /services/testSpring.testSpringHttpSoap12Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:bcae82e9-4027-43c5-bd7a-cbfa885aaf33, Direction: request, END = ______________________, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body/></soapenv:Envelope>
You must restart the ESB after placing the jar in repository/components/lib
These are the steps for spring mediator in brief as Isuru explained above
Create spring mediator library by extending AbstractMediator
Copy into ESB_HOME/repository/components/lib
Re-start the server
Register springtest.xml file in the Registry
(http://madhukaudantha.blogspot.com/2012/07/wso2-esb-proxy-from-registry.html up to step 5 as Isuru explained)
Then, create a Custom proxy with Spring Mediator.
In there,
add Bean as “springtest” (defined bean id for the mediator class within the xml file)
Select the Key as where the configuration registry file stored according to the 4th step.
Ex : If you have stored that springtest.xml file into path “_system/config/repository/”
Select Key as “/_system/config/repository/springtest.xml”
Note:
Verify in ESB_HOME/repository/components/dropins folder for OSGI
bundle of the mediator of the created spring mediator library which
is copied into ESB_HOME/repository/components/lib. If it is not there
after restarting server, it may be a problem in created mediator
library.
As well as, put unique package name for the mediator class to avoid
conflicts with other mediator class in
ESB_HOME/repository/components/lib.
Keep in mind to add unique bean id for the .xml file which is
registered in the registry when you registered .xml file in 4th step.
This is because of the esb finds the springsample.xml file in the path repository/conf/sample/resources
<parameter name="root">file:repository/conf/sample/resources/</parameter>
But the springsample.xml file location is in repository/samples/resources/ . Therefore it should be corrected as the following,
<parameter name="root">file:repository/samples/resources/</parameter>
In documentation, the configuration is not correct, If you start the esb by the command wso2esb-samples -sn 470 (as mentioned in the documentation) the esb will load the file in repository/samples/synapse_sample_470.xml where in this file above parameter is correctly configured.
Hope this will solve your problem :)
UPDATED:
According to your comment, as your are directly using sample spring example, this occur due to permission of the file trying to access, Or this can be due to file path error. So please try with absolute file url.
when i send a message, the only error message i got is this one
ERROR - SpringMediator No bean named 'springtest' is defined
so it means, the config file has been found. But what about the instanciation of the bean inside, i cannot see any explicit error. The jar file is in components/lib and i can see it also in dropins folder.
:/

Weird behaviour of import tag in spring's configuration file

I am working on the spring spring-3.2.2. I have created two java projects in eclipse.
SpringTest
Testclasspath
SpringTest project is having the below beans.xml in which the one bean is defined.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.spring.HelloWorld" init-method="testUpdate" scope="prototype">
<property name="message" value="Hello World!"/>
</bean>
</beans>
I have created the jar springtest.jar of the project SpringTest and it is been added in the classpath of the project Testclasspath. Bean configuration file for the Testclasspath project is talentacquisition.xml and it is importing the beans.xml file of the Springtest project. Please find the below content of talentacquisition.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<import resource="Beans.xml"/>
<bean id="juggler" class="com.springaction.springidol.Juggler" />
</beans>
I am confused with behavior of the import tag in the talentacquisition.xml How it is able to locate the Beans.xml which is present in the jar (springtest.jar) in the classpath and able to load the beans? Why spring is not giving any error ? Don't I have to modify the import tag in the talentacqusition.xml to following
<import resource="classpath:Beans.xml"/>
If import is able to locate the file Beans.xml , then when should we use classpath: and classpath* :?
ResourceLoaders are responsible for how Spring loads the resource. From the reference manual
The location path or paths supplied to an ApplicationContext
constructor are actually resource strings, and in simple form are
treated appropriately to the specific context implementation.
ClassPathXmlApplicationContext treats a simple location path as a
classpath location. You can also use location paths (resource strings)
with special prefixes to force loading of definitions from the
classpath or a URL, regardless of the actual context type.
The ClassPathXmlApplicationContext you're instantiating "treats a simple location path as a classpath location", i.e. it treats "Beans.xml" as "classpath:Beans.xml". Similarly, FileSystemXmlApplicationContext would treat "Beans.xml" as "file:Beans.xml".
Section 6.7 of the manual has more details too.

Resources