Skip to content

Commit 0732ec5

Browse files
committed
Merge pull request #9 from garyrussell/feed
Use RSS Feed Instead of Twitter
2 parents 516257c + a140915 commit 0732ec5

File tree

11 files changed

+87
-112
lines changed

11 files changed

+87
-112
lines changed

README.adoc

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ projects: [spring-integration]
1414
:icons: font
1515
:source-highlighter: prettify
1616
:project_id: gs-integration
17-
This guide walks you through the process of using Spring Integration to create a simple application that retrieves data from Twitter, manipulates the data, and then writes it to a file.
17+
This guide walks you through the process of using Spring Integration to create a simple application that retrieves data from Twitter, manipulates the data, and then writes it to a file. This guide uses traditional Spring Integration XML configuration; other guides exist showing the use of JavaConfig/DSL with and without JDK 8 Lambda expressions.
1818

1919
== What you'll build
2020

@@ -34,55 +34,41 @@ include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/
3434

3535

3636
[[initial]]
37-
== Define an integration plan
37+
== Define an integration flow
3838

39-
For this guide's sample application, you will define a Spring Integration plan that reads tweets from Twitter, transforms them into an easily readable `String`, and appends that `String` to the end of a file.
39+
For this guide's sample application, you will define a Spring Integration flow that reads blog posts from Spring IO's RSS feed, transforms them into an easily readable `String` consisting of the post title and the URL for the post, and appends that `String` to the end of a file `/tmp/si/SpringBlog`.
4040

41-
To define an integration plan, you simply create a Spring XML configuration with a handful of elements from Spring Integration's XML namespaces. Specifically, for the desired integration plan, you work with elements from these Spring Integration namespaces: core, twitter, and file.
41+
To define an integration flow, you simply create a Spring XML configuration with a handful of elements from Spring Integration's XML namespaces. Specifically, for the desired integration flow, you work with elements from these Spring Integration namespaces: core, feed, and file.
4242

43-
The following XML configuration file defines the integration plan:
43+
The following XML configuration file defines the integration flow:
4444

45-
`src/main/resources/hello/integration.xml`
45+
`src/main/resources/blog/integration.xml`
4646
[source,xml]
4747
----
48-
include::complete/src/main/resources/hello/integration.xml[]
48+
include::complete/src/main/resources/blog/integration.xml[]
4949
----
5050

5151
As you can see, three integration elements are in play here:
5252

53-
* `<twitter:search-inbound-channel-adapter>`. An inbound adapter that searches Twitter for tweets with "#HelloWorld" in the text. It is injected with a `TwitterTemplate` from {SpringSocial}[Spring Social] to perform the actual search. As configured here, it polls every 5 seconds. Any matching tweets are placed into a channel named "tweets" (corresponding with the adapter's ID).
54-
* `<int:transformer>`. Transformed tweets in the "tweets" channel, extracting the tweet's author (`payload.fromUser`) and text (`payload.text`) and concatenating them into a readable `String`. The `String` is then written through the output channel named "files".
55-
* `<file:outbound-channel-adapter>`. An outbound adapter that writes content from its channel (here named "files") to a file. Specifically, as configured here, it will append anything in the "files" channel to a file at `/tmp/si/HelloWorld`.
53+
* `<feed:inbound-channel-adapter>`. An inbound adapter that retrieves the posts, one per poll. As configured here, it polls every 5 seconds. The posts are placed into a channel named "news" (corresponding with the adapter's ID).
54+
* `<int:transformer>`. Transforms entries (`com.rometools.rome.feed.synd.SyndEntry`) in the "news" channel, extracting the entry's title (`payload.title`) and link (`payload.link`) and concatenating them into a readable `String` (adding a newline). The `String` is then sent to the output channel named "file".
55+
* `<file:outbound-channel-adapter>`. An outbound channel adapter that writes content from its channel (here named "file") to a file. Specifically, as configured here, it will append anything in the "file" channel to a file at `/tmp/si/SpringBlog`.
5656

5757
This simple flow is illustrated like this:
5858

59-
image::images/tweetToFile.png[A flow plan that reads tweets from Twitter, transforms them to a String, and appends them to a file.]
60-
61-
The integration plan references two beans that aren't defined in `integration.xml`: the "twitterTemplate" bean that is injected into the search inbound adapter and the "newline" bean referenced in the transformer. Those beans will be declared separately in JavaConfig as part of the main class of the application.
59+
image::images/blogToFile.png[A flow that reads RSS feed entries, transforms them to a String, and appends them to a file.]
6260

6361
== Make the application executable
6462

65-
Although it is common to configure a Spring Integration plan within a larger application, perhaps even a web application, there's no reason that it can't be defined in a simpler standalone application. That's what you do next, creating a main class that kicks off the integration plan and also declares a handful of beans to support the integration plan. You also build the application into a standalone executable JAR file.
63+
Although it is common to configure a Spring Integration flow within a larger application, perhaps even a web application, there's no reason that it can't be defined in a simpler standalone application. That's what you do next, creating a main class that kicks off the integration flow and also declares a handful of beans to support the integration flow. You also build the application into a standalone executable JAR file. We use Spring Boot's `SpringApplication` to create the application context.
6664

6765

68-
`src/main/java/hello/Application.java`
66+
`src/main/java/blog/Application.java`
6967
[source,java]
7068
----
71-
include::complete/src/main/java/hello/Application.java[]
69+
include::complete/src/main/java/blog/Application.java[]
7270
----
7371

74-
As you can see, this class provides a `main()` method that loads the Spring application context. It's also annotated as a `@Configuration` class, indicating that it will contain bean definitions.
75-
76-
Specifically, three beans are created in this class:
77-
78-
* The `newline()` method creates a simple `String` bean containing the underlying system's newline character(s). This is used in the integration plan to place a newline at the end of the transformed tweet `String`.
79-
* The `twitterTemplate()` method defines a `TwitterTemplate` bean that is injected into the `<twitter:search-inbound-channel-adapter>`.
80-
* The `oauth2Template()` method defines a Spring Social `OAuth2Template` bean used to obtain a client access token when creating the `TwitterTemplate` bean.
81-
82-
The `oauth2Template()` method references the `Environment` to get "clientId" and "clientSecret" properties. Those properties are ultimately client credentials you are given when you {gs-register-twitter-app}[register your application with Twitter]. Fetching them from the `Environment` means you don't have to hardcode them in this configuration class. You'll need them when you <<run>>, though.
83-
84-
Finally, notice that `Application` is configured with `@ImportResource` to import the integration plan defined in `/hello/integration.xml`.
85-
8672
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_an_executable_jar_subhead.adoc[]
8773
include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/master/build_an_executable_jar_with_both.adoc[]
8874

@@ -91,30 +77,27 @@ include::https://raw.githubusercontent.com/spring-guides/getting-started-macros/
9177

9278
Now you can run the application from the jar:
9379
....
94-
java -DclientId={YOUR CLIENT ID} -DclientSecret={YOUR CLIENT SECRET} -jar build/libs/{project_id}-0.1.0.jar
80+
java -jar build/libs/{project_id}-0.1.0.jar
9581
9682
... app starts up ...
9783
....
9884

99-
Make sure you specify your application's client ID and secret in place of the placeholders shown here.
85+
Once the application starts up, it connects to the RSS feed and starts fetching blog posts. The application processes those posts through the integration flow you defined, ultimately appending the post information to a file at `/tmp/si/SpringBlog`.
10086

101-
Once the application starts up, it connects to Twitter and starts fetching tweets that match the search criteria of "#HelloWorld". The application processes those tweets through the integration plan you defined, ultimately appending the tweet's author and text to a file at `/tmp/si/HelloWorld`.
102-
103-
After the application has been running for awhile, you should be able to view the file at `/tmp/si/HelloWorld` to see the data from a handful of tweets. On a UNIX-based operating system, you can also choose to tail the file to see the results as they are written:
87+
After the application has been running for awhile, you should be able to view the file at `/tmp/si/SpringBlog` to see the data from a handful of posts. On a UNIX-based operating system, you can also choose to tail the file to see the results as they are written:
10488

10589
----
106-
tail -f /tmp/si/HelloWorld
90+
tail -f /tmp/si/SpringBlog
10791
----
10892

109-
You should see something like this (the actual tweets may differ):
93+
You should see something like this (the actual news will differ):
11094

11195
....
112-
BrittLieTjauw : Now that I'm all caught up on the bachelorette I can leave my room #helloworld
113-
mishra_ravish : Finally, integrated #eclim. #Android #HelloWorld
114-
NordstrmPetite : Pink and fluffy #chihuahua #hahalol #boo #helloworld http://t.co/lelHhFN3gq
115-
GRhoderick : Ok Saint Louis, show me what you got. #HelloWorld
96+
Spring Integration Java DSL 1.0 GA Released @ https://spring.io/blog/2014/11/24/spring-integration-java-dsl-1-0-ga-released
97+
This Week in Spring - November 25th, 2014 @ https://spring.io/blog/2014/11/25/this-week-in-spring-november-25th-2014
98+
Spring Integration Java DSL: Line by line tutorial @ https://spring.io/blog/2014/11/25/spring-integration-java-dsl-line-by-line-tutorial
99+
Spring for Apache Hadoop 2.1.0.M2 Released @ https://spring.io/blog/2014/11/14/spring-for-apache-hadoop-2-1-0-m2-released
116100
....
117101

118102
== Summary
119-
Congratulations! You have developed a simple application that uses Spring Integration to fetch tweets from Twitter, process them, and write them to a file.
120-
103+
Congratulations! You have developed a simple application that uses Spring Integration to fetch blog posts from spring.io, process them, and write them to a file.

complete/build.gradle

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,18 @@ repositories {
2727

2828
dependencies {
2929
compile("org.springframework.boot:spring-boot-starter-integration")
30-
compile("org.springframework.integration:spring-integration-twitter:4.0.3.RELEASE")
30+
compile("org.springframework.integration:spring-integration-feed:4.0.4.RELEASE")
3131
testCompile("junit:junit")
3232
}
3333

3434
task wrapper(type: Wrapper) {
3535
gradleVersion = '1.11'
3636
}
37+
38+
eclipse {
39+
project {
40+
natures += 'org.springframework.ide.eclipse.core.springnature'
41+
}
42+
}
43+
44+

complete/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
<dependency>
2323
<groupId>org.springframework.integration</groupId>
24-
<artifactId>spring-integration-twitter</artifactId>
25-
<version>4.0.3.RELEASE</version>
24+
<artifactId>spring-integration-feed</artifactId>
25+
<version>4.0.4.RELEASE</version>
2626
</dependency>
2727
</dependencies>
2828

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package blog;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.context.ConfigurableApplicationContext;
5+
6+
public class Application {
7+
public static void main(String[] args) throws Exception {
8+
ConfigurableApplicationContext ctx = new SpringApplication("/blog/integration.xml").run(args);
9+
System.out.println("Hit Enter to terminate");
10+
System.in.read();
11+
ctx.close();
12+
}
13+
14+
}

complete/src/main/java/hello/Application.java

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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:file="http://www.springframework.org/schema/integration/file"
6+
xmlns:feed="http://www.springframework.org/schema/integration/feed"
7+
xsi:schemaLocation="http://www.springframework.org/schema/integration/feed http://www.springframework.org/schema/integration/feed/spring-integration-feed.xsd
8+
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
9+
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
10+
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
11+
12+
<feed:inbound-channel-adapter id="news" url="https://spring.io/blog.atom">
13+
<int:poller fixed-rate="5000"/>
14+
</feed:inbound-channel-adapter>
15+
16+
<int:transformer
17+
input-channel="news"
18+
expression="payload.title + ' @ ' + payload.link + '#{systemProperties['line.separator']}'"
19+
output-channel="file"/>
20+
21+
<file:outbound-channel-adapter id="file"
22+
mode="APPEND"
23+
charset="UTF-8"
24+
directory="/tmp/si"
25+
filename-generator-expression="'SpringBlog'"/>
26+
27+
</beans>

complete/src/main/resources/hello/integration.xml

Lines changed: 0 additions & 29 deletions
This file was deleted.

images/blogToFile.png

19.1 KB
Loading

images/tweetToFile.png

-19 KB
Binary file not shown.

initial/build.gradle

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,18 @@ repositories {
2727

2828
dependencies {
2929
compile("org.springframework.boot:spring-boot-starter-integration")
30-
compile("org.springframework.integration:spring-integration-twitter:4.0.3.RELEASE")
30+
compile("org.springframework.integration:spring-integration-feed:4.0.4.RELEASE")
3131
testCompile("junit:junit")
3232
}
3333

3434
task wrapper(type: Wrapper) {
3535
gradleVersion = '1.11'
3636
}
37+
38+
eclipse {
39+
project {
40+
natures += 'org.springframework.ide.eclipse.core.springnature'
41+
}
42+
}
43+
44+

0 commit comments

Comments
 (0)