With Spring you can collect classes and there inherits tree into list .
For an example :
Use the autowire spring context declaration:
@Configuration
@ComponentScan("com.model.cars")
public class SpringContext {
}
We can declare a ctor in a @component Road class
@Autowired
public Road(List<Car> pCar) {
}
The auto wired process scans the com.model.cars directory for all the components that inherit from Car class (and the car class itself if exists in the scanning directory ) and construct the car Ctor parameter pCar list accordingly .
So if the com.model.cars path contains the following component
@Component
Class sosita extends Car
and
@Component
Class Subaru extends sosita
The Road ctor will be called with a 2 items list of sosita and Subaru
Reference:
http://lkrnac.net/blog/2014/04/30/load-inheritance-tree/
הבלוג שלי מכיל פרסומים של ההתעסקות המקצועית היום יומית שלי שלי בתור ארכיטקט ומוביל טכנולוגיות
יום שלישי, 6 במאי 2014
Spring inheritance tree
יום חמישי, 27 ביוני 2013
Write and read from mongodb using spring integration
I extend the spring integration demo:Samples (Basic) – MongoDb and add a read capabilities to the MongoDbOutboundAdapterDemo class.
The spring context
1: <?xml version="1.0" encoding="UTF-8"?>2: <beans xmlns="http://www.springframework.org/schema/beans"3: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"4: xmlns:int="http://www.springframework.org/schema/integration"5: xmlns:int-mongodb="http://www.springframework.org/schema/integration/mongodb"6: xmlns:mongo="http://www.springframework.org/schema/data/mongo"7: xmlns:beans="http://www.springframework.org/schema/beans"8: xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd9: http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.2.xsd10: http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd11: http://www.springframework.org/schema/integration/mongodb http://www.springframework.org/schema/integration/mongodb/spring-integration-mongodb-2.2.xsd">12:13: <mongo:db-factory id="mongoDbFactory" dbname="test"/>14:15: <int-mongodb:outbound-channel-adapter id="deafultAdapter" />16:17: <int-mongodb:outbound-channel-adapter id="adapterWithConverter" mongo-converter="stringConverter"/>18:19: <int-mongodb:inbound-channel-adapter id="simpleInboundAdapter" channel="outputChannel"20: query="{address.state : 'CA'}">21: <int:poller fixed-rate="1000" max-messages-per-poll="1"/>22: </int-mongodb:inbound-channel-adapter>23:24: <int:publish-subscribe-channel id="outputChannel">25: </int:publish-subscribe-channel>26: </beans>27:
The code
1: package org.springframework.integration.samples.mongodb.outbound;2:3: import org.springframework.context.ApplicationContext;4: import org.springframework.context.support.FileSystemXmlApplicationContext;5: import org.springframework.integration.Message;6: import org.springframework.integration.MessageChannel;7: import org.springframework.integration.core.MessageHandler;8: import org.springframework.integration.core.SubscribableChannel;9: import org.springframework.integration.message.GenericMessage;10: import org.springframework.integration.samples.mongodb.domain.Address;11: import org.springframework.integration.samples.mongodb.domain.Person;12: import org.springframework.integration.samples.mongodb.util.DemoUtils;13: /**14: *15: * @author of the orginal source Oleg Zhurakousky16: * @Add reading Zvika Peer17: */18: public class MongoDbOutboundAdapterDemo {19:20:21: public static void main(String[] args) throws Exception {22: DemoUtils.prepareMongoFactory(); // will clean up MOngoDb23: new MongoDbOutboundAdapterDemo().runDefaultAdapter();24: }25:26: public void runDefaultAdapter() throws Exception {27:28: ApplicationContext context =29: new FileSystemXmlApplicationContext(30: "C:\\learn\\spring\\integration\\samples\\basic\\mongodb\\src\\main\\java\\org\\springframework\\integration\\samples\\mongodb\\outbound\\mongodb-out-config.xml"31: );32:33: MessageChannel messageChannel = context.getBean("deafultAdapter", MessageChannel.class);34: messageChannel.send(new GenericMessage<Person>(this.createPersonA()));35: messageChannel.send(new GenericMessage<Person>(this.createPersonB()));36: messageChannel.send(new GenericMessage<Person>(this.createPersonC()));37:38: SubscribableChannel outputChannel = context.getBean("outputChannel", SubscribableChannel.class);39:40: outputChannel.subscribe(new MessageHandler()41: {42: @Override43: public void handleMessage(Message<?> msg)44: {45: System.out.println("==> HelloWorldDemo Async message: " + msg.getPayload());46: }47: });48:49: Thread.sleep(4000);50: System.out.println("Finished");51: }52: }
The result
Finished
==> HelloWorldDemo Async message: [{ "_id" : { "$oid" : "51c945b3fe3a5df7ab5f7a3d"} , "_class" : "org.springframework.integration.samples.mongodb.domain.Person" , "fname" : "John" , "lname" : "Doe" , "address" : { "street" : "3401 Hillview Ave" , "city" : "Palo Alto" , "zip" : "94304" , "state" : "CA"}}, { "_id" : { "$oid" : "51c945b3fe3a5df7ab5f7a3e"} , "_class" : "org.springframework.integration.samples.mongodb.domain.Person" , "fname" : "Josh" , "lname" : "Doe" , "address" : { "street" : "123 Main st" , "city" : "San Francisco" , "zip" : "94115" , "state" : "CA"}}]
Resources:
http://static.springsource.org/spring-integration/reference/html/mongodb.html
יום שישי, 7 ביוני 2013
Create an executable jar using maven
I found several resources about how to make an executable jar using maven.
I want the the executable jar file to contain all the dependencies jars that the project need .
In general the following steps are used to generate the jar file:
Create the sample eclipse project :1: $ mvn archetype:generate -DgroupId=my.learn -DartifactId=mavenToExeJar -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false2:3: cd mavenToExeJar4:5: mvn eclipse:eclipse
The main class:
1: package my.learn;2: import org.springframework.context.ApplicationContext;3: import org.springframework.context.support.FileSystemXmlApplicationContext;4: public class App5: {6: public static void main( String[] args )7: {8: ApplicationContext context = new FileSystemXmlApplicationContext(9: "SpringXMLConfig.xml");10: MyBean theMyBean = (MyBean) context.getBean("MyBean");11: System.out.println( "Hello:" + theMyBean.getName() );12: }13: }14:
The bean :
1: package my.learn;2: public class MyBean {3: private String mName;4:5: public String getName()6: {7: return mName;8: }9: public void setName(String pValue)10: {11: mName = pValue;12: }13: }
The spring context file
1: <?xml version="1.0" encoding="windows-1252"?>2: <beans xmlns="http://www.springframework.org/schema/beans"3: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"4: xmlns:aop="http://www.springframework.org/schema/aop"5: xmlns:c="http://www.springframework.org/schema/c"6: xmlns:context="http://www.springframework.org/schema/context"7: xmlns:flow="http://www.springframework.org/schema/webflow-config"8: xmlns:jms="http://www.springframework.org/schema/jms"9: xmlns:lang="http://www.springframework.org/schema/lang"10: xmlns:p="http://www.springframework.org/schema/p"11: xmlns:tx="http://www.springframework.org/schema/tx"12: xmlns:util="http://www.springframework.org/schema/util"13:14: xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd15: http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd16: http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd17: http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd18: http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.2.xsd19: http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.2.xsd20: http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd21: http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd22: ">23: <bean id="MyBean" class="my.learn.MyBean">24: <property name="name" value="Abdala" />25: </bean>26: </beans>
The maven xml pom file :
1: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"2: xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">3: <modelVersion>4.0.0</modelVersion>4: <groupId>my.learn</groupId>5: <artifactId>mavenToExeJar</artifactId>6: <packaging>jar</packaging>7: <version>1.0-SNAPSHOT</version>8: <name>mavenToExeJar</name>9: <url>http://maven.apache.org</url>10: <properties>11: <jdk.version>1.6</jdk.version>12: <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>13: </properties>14: <dependencies>15: <dependency>16: <groupId>junit</groupId>17: <artifactId>junit</artifactId>18: <version>3.8.1</version>19: <scope>test</scope>20: </dependency>21:22: <!-- Spring framework -->23: <dependency>24: <groupId>org.springframework</groupId>25: <artifactId>spring-context</artifactId>26: <version>3.2.3.RELEASE</version>27: </dependency>28: </dependencies>29: <build>30: <plugins>31: <plugin>32: <groupId>org.apache.maven.plugins</groupId>33: <artifactId>maven-jar-plugin</artifactId>34: <version>2.3</version>35: <configuration>36: <archive>37: <manifest>38: <mainClass>my.learn.App</mainClass>39: <addClasspath>true</addClasspath>40: </manifest>41: </archive>42: </configuration>43: </plugin>44: <plugin>45: <groupId>org.dstovall</groupId>46: <artifactId>onejar-maven-plugin</artifactId>47: <version>1.4.4-SNAPSHOT</version>48: <executions>49: <execution>50: <configuration>51: <!-- Optional52: <onejarVersion>0.97</onejarVersion>53: Optional, use only if you need to include native libraries(dll's)54: <directory>${project.build.directory}/dllextract</directory>55: <include>test.dll</include>56: </includes>57: </fileSet>58: </binlibs>-->59: <!-- Optional, default is false -->60: <attachToBuild>true</attachToBuild>61: <!-- Optional, default is "onejar" -->62: <classifier>onejar</classifier>63: </configuration>64: <goals>65: <goal>one-jar</goal>66: </goals>67: </execution>68: </executions>69: </plugin>70: </plugins>71: </build>72:73: <pluginRepositories>74: <pluginRepository>75: <id>onejar-maven-plugin.googlecode.com</id>76: <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo-snapshot</url>77: </pluginRepository>78: </pluginRepositories>79: </project>80:
The folder structure
After compiling the project :
mvn compiler:compile etc
The packing stage :
mvn package
creates the executable jar file. (don't forget to copy the spring context file to the right location )
Execute the jar file
C:\learn\java\maven\executableJar\mavenToExeJar\target>java -jar mavenToExeJar-1
.0-SNAPSHOT.one-jar.jar
and walla :
Jun 08, 2013 10:18:22 AM org.springframework.context.support.AbstractApplication
Context prepareRefresh
INFO: Refreshing org.springframework.context.support.FileSystemXmlApplicationCon
text@16fdac: startup date [Sat Jun 08 10:18:22 IDT 2013]; root of context hierar
chy
Jun 08, 2013 10:18:22 AM org.springframework.beans.factory.xml.XmlBeanDefinition
Reader loadBeanDefinitions
INFO: Loading XML bean definitions from file [C:\learn\java\maven\executableJar\
mavenToExeJar\target\SpringXMLConfig.xml]
Jun 08, 2013 10:18:22 AM org.springframework.beans.factory.support.DefaultListab
leBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.
DefaultListableBeanFactory@7588c: defining beans [MyBean]; root of factory hiera
rchy
Hello:Abdalla
Resources:
http://www.mkyong.com/maven/how-to-create-a-jar-file-with-maven/
http://one-jar.sourceforge.net/
ApplicationContext loading
There is two ways to load application context xml file in spring: classpathxmlapplicationcontext or filesystemxmlapplicationcontext.
FileSystemXmlApplicationContext:
Loads the application context acoording to a full path for an example
1: ApplicationContext context = new FileSystemXmlApplicationContext(2: "I:\\Learn\\java\\maven\\executableJar\\mavenToExeJar\\SpringXMLConfig.xml");
The current path can be obtained by :
1: final String dir = System.getProperty("user.dir");2: System.out.println("current dir = " + dir);
classpathxmlapplicationcontext
The spring application context should be in the CLASSPATH
Getting the current class path can be done by:
1: String theClassPath = System.getProperty("java.class.path");2: System.out.println("theClassPath dir = " + theClassPath);3:
An example for using classpathxmlapplicationcontext :
1: ApplicationContext context = new ClassPathXmlApplicationContext (2: "SpringXMLConfig.xml");
Resources
http://en.wikipedia.org/wiki/Classpath_(Java)
http://codeissue.com/issues/i84e1f376448bef/classpathxmlapplicationcontext-vs-filesystemxmlapplicationcontext
יום חמישי, 6 ביוני 2013
Sprint Context File is packed to
When creating an executable jar of spring project
The jar packing procedure may pack the spring context file as well.
So the jar file will contain the file and the program that use spring will load the context from the context file in the jar bundle.
The context file / files should be exclude from the jar in order to allow the configurability and deploy to the jar directory before executing the jar .
יום שישי, 24 במאי 2013
Custom scope in spring
Spring frameworks enabled extending its objects creation scopes by allowing to add custom scope to the system.
I have found this capacity very use full in enterprise system when I wants to access the same object from application layers that doesn’t share the same spring context.(Every layer construct its own spring application context and get the same bean.
In order to make an object instance available to all the system the solution used to store its state in a cache.When the spring frame work is trying to retrieve an object that is declared with the Enterprise scope it try to find if the object exists in the cache if yes it retrieve the object from the cache and return it .If the object doen’t exists in the cache the scope creates the instance store it in the cache and return it .
In order to implement the custom scope we need to implement the org.springframework.beans.factory.config.Scope interface.
The most important method to override is the get method .
A sample scope implementation :
package javaapplicationbasicspring;
import org.springframework.beans.factory.ObjectFactory;
import java.util.HashMap;
public class myCustomScop implements org.springframework.beans.factory.config.Scope
{
static HashMap<String , Object> mObjectCache;
public myCustomScop()
{
mObjectCache = new HashMap<>();
}
@Override
public Object get(String string, ObjectFactory<?> of) {
if (mObjectCache.containsKey(string))
{
return mObjectCache.get(string);
}
Object theSingletonObject = of.getObject();
mObjectCache.put(string, theSingletonObject);
return theSingletonObject;
}
@Override
public Object remove(String string) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void registerDestructionCallback(String string, Runnable r) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Object resolveContextualObject(String string) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String getConversationId() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
The of.getObject(); construct and update an object .
The bean definition:
package javaapplicationbasicspring;
public class SimpleAccountService {
private String mString;
private SimpleAccountService mParent;
private String mTestValue = "Nothing";
public String getTestValue() {
return mTestValue;
}
public void setTestValue(String mTestValue) {
this.mTestValue = mTestValue;
}
public SimpleAccountService()
{
}
}
The spring context 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:context="http://www.springframework.org/schema/context"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd
">
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="Enterprise">
<map>
<entry key="Enterprise">
<bean class="javaapplicationbasicspring.myCustomScop"/>
</entry>
</map>
</property>
</bean>
<bean id="accountService" class="javaapplicationbasicspring.SimpleAccountService" scope="Enterprise">
<property name="Value">
<value>Hello Zvika</value>
</property>
</bean>
</beans>
The test case :
ClassPathXmlApplicationContext appContextParent = new ClassPathXmlApplicationContext(
new String[] {"resources/ParentSpringXMLConfig.xml"} );
ClassPathXmlApplicationContext appContextParent2 = new ClassPathXmlApplicationContext(
new String[] {"resources/ParentSpringXMLConfig.xml"} );
SimpleAccountService theSimpleAccountService =
(SimpleAccountService)appContextParent2.getBea("accountService");
SimpleAccountService theSimpleAccountService2 =
(SimpleAccountService)appContextParent.getBean("accountService");
theSimpleAccountService.setTestValue ("Zvika");
System.out.print ("Hello: " + theSimpleAccountService2.getTestValue());
and the result is :
Hello: Zvika
יום שלישי, 14 במאי 2013
Spring context scope
The spring Ioc container is not singleton .every call to ClassPathXmlApplicationContext generate a separate spring Ioc context .
Lets define the following spring bean :
<bean id="accountService" class="javaapplicationbasicspring.SimpleAccountService" scope="singleton">
</bean>
(I know scope="singleton” is the default context)
The SimpleAccountService class has one property :
private String mTestValue = "Nothing";
public String getTestValue() {
return mTestValue;
}
public void setTestValue(String mTestValue) {
this.mTestValue = mTestValue;
Lets do the following text :
ClassPathXmlApplicationContext appContextParent = new ClassPathXmlApplicationContext(
new String[] {"resources/ParentSpringXMLConfig.xml"});
ClassPathXmlApplicationContext appContextParent2 = new ClassPathXmlApplicationContext(
new String[] {"resources/ParentSpringXMLConfig.xml"} );
SimpleAccountService theSimpleAccountService =
(SimpleAccountService)appContextParent2.getBean("accountService");
SimpleAccountService theSimpleAccountService2 =
(SimpleAccountService)appContextParent.getBean("accountService");
theSimpleAccountService.setTestValue ("Zvika");
System.out.print ("Hello: " + theSimpleAccountService2.getTestValue())
The result is :
Hello: Nothing
we saw that each application context has its one instance .
I don't like it because an application should take care of managing the single spring context in it deferent layers , modules etc instead of taking care by the spring infrastructure .
יום שני, 13 במאי 2013
About spring integration Hello world sample
The Hello world demo construct a simple integration graph:
Where the message enter the input channel processed by the service activator and exit form the output Chanel .
The declaration in the spring integration descriptor xml:
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
<channel id="inputChannel"/>
<channel id="outputChannel">
<queue capacity="10"/>
</channel>
<service-activator input-channel="inputChannel"
output-channel="outputChannel"
ref="helloService"
method="sayHello"/>
<beans:bean id="helloService" class="org.springframework.integration.samples.helloworld.HelloService"/>
</beans:beans>
Note that the output channel is declared with a queue of 10 messages allowed to be stored before consuming .
The code for using the integration graph:
The pojo Hello service :
public class HelloService
{
public String sayHello(String name) {
return "Hello " + name;
}
}
The input and the output channels reference:
AbstractApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/spring/integration/helloWorldDemo.xml", HelloWorldApp.class);
MessageChannel inputChannel = context.getBean("inputChannel", MessageChannel.class);
PollableChannel outputChannel = context.getBean("outputChannel", PollableChannel.class);
Lets try to send 14 messages behind the output channel capacity :
for ( int i= 1 ; i < 14 ; i ++)
{
logger.info("Sending no:" + Integer.toString (i));
inputChannel.send(new GenericMessage<String>("Mr no" + Integer.toString (i)));
}
The application stack waiting for the output channel to be consumed:
08:35:01.874 INFO [main][org.springframework.integration.samples.helloworld.HelloWorldApp] Sending no:9
08:35:01.875 INFO [main][org.springframework.integration.samples.helloworld.HelloWorldApp] Sending no:10
08:35:01.875 INFO [main][org.springframework.integration.samples.helloworld.HelloWorldApp] Sending no:11
Trying to receive the message in endless loop :
while (true)
{
Message theMessage = outputChannel.receive(0);
logger.info("==> HelloWorldDemo: " + theMessage.getPayload());
}
cause a java.lang.NullPointerException when the output channel queue gets empty .
In the next post I will consume the message async in order to void the stacking of the sender and the null exception in the receiver channel.