282 lines
14 KiB
HTML
282 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<!--
|
|
| Generated by Apache Maven Doxia at 2016-04-24
|
|
| Rendered using Apache Maven Fluido Skin 1.3.0
|
|
-->
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="author" content="kebernet" />
|
|
<meta name="Date-Creation-yyyymmdd" content="20111206" />
|
|
<meta name="Date-Revision-yyyymmdd" content="20160424" />
|
|
<meta http-equiv="Content-Language" content="en" />
|
|
<title>ROME - Certiorem Tutorial</title>
|
|
<link rel="stylesheet" href="../css/apache-maven-fluido-1.3.0.min.css" />
|
|
<link rel="stylesheet" href="../css/site.css" />
|
|
<link rel="stylesheet" href="../css/print.css" media="print" />
|
|
|
|
|
|
<script type="text/javascript" src="../js/apache-maven-fluido-1.3.0.min.js"></script>
|
|
|
|
|
|
</head>
|
|
<body class="topBarDisabled">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="http://github.com/rometools/rome">
|
|
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 10000;"
|
|
src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"
|
|
alt="Fork me on GitHub">
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<div class="container-fluid">
|
|
<div id="banner">
|
|
<div class="pull-left">
|
|
<a href="../index.html" id="bannerLeft">
|
|
<img src="../images/romelogo.png" alt="ROME"/>
|
|
</a>
|
|
</div>
|
|
<div class="pull-right"> </div>
|
|
<div class="clear"><hr/></div>
|
|
</div>
|
|
|
|
<div id="breadcrumbs">
|
|
<ul class="breadcrumb">
|
|
|
|
|
|
|
|
|
|
|
|
<li id="publishDate" class="pull-right">Last Published: 2016-04-24</li> <li class="divider pull-right">|</li>
|
|
<li id="projectVersion" class="pull-right">Version: 1.7.0-SNAPSHOT</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
<div class="row-fluid">
|
|
<div id="leftColumn" class="span3">
|
|
<div class="well sidebar-nav">
|
|
|
|
|
|
<ul class="nav nav-list">
|
|
<li class="nav-header">Rome</li>
|
|
|
|
<li>
|
|
|
|
<a href="../index.html" title="Overview">
|
|
<i class="none"></i>
|
|
Overview</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../HowRomeWorks/index.html" title="How Rome Works">
|
|
<i class="icon-chevron-right"></i>
|
|
How Rome Works</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../RssAndAtOMUtilitiEsROMEV0.5AndAboveTutorialsAndArticles/index.html" title="Tutorials And Articles">
|
|
<i class="none"></i>
|
|
Tutorials And Articles</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../ROMEReleases/index.html" title="Releases">
|
|
<i class="icon-chevron-right"></i>
|
|
Releases</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../ROMEDevelopmentProposals/index.html" title="ROME Development Proposals">
|
|
<i class="none"></i>
|
|
ROME Development Proposals</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../Modules/index.html" title="Modules">
|
|
<i class="icon-chevron-right"></i>
|
|
Modules</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../Fetcher/index.html" title="Fetcher">
|
|
<i class="icon-chevron-right"></i>
|
|
Fetcher</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../Opml/index.html" title="OPML">
|
|
<i class="none"></i>
|
|
OPML</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../Propono/index.html" title="Propono">
|
|
<i class="none"></i>
|
|
Propono</a>
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="../Certiorem/index.html" title="Certiorem">
|
|
<i class="icon-chevron-down"></i>
|
|
Certiorem</a>
|
|
<ul class="nav nav-list">
|
|
|
|
<li class="active">
|
|
|
|
<a href="#"><i class="none"></i>Tutorial</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-header">Project Documentation</li>
|
|
|
|
<li>
|
|
|
|
<a href="../project-info.html" title="Project Information">
|
|
<i class="icon-chevron-right"></i>
|
|
Project Information</a>
|
|
</li>
|
|
</ul>
|
|
|
|
|
|
|
|
<hr class="divider" />
|
|
|
|
<div id="poweredBy">
|
|
<div class="clear"></div>
|
|
<div class="clear"></div>
|
|
<div class="clear"></div>
|
|
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
|
|
<img class="builtBy" alt="Built by Maven" src="../images/logos/maven-feather.png" />
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="bodyColumn" class="span9" >
|
|
|
|
<div class="section">
|
|
<h2>Certiorem Tutorial<a name="Certiorem_Tutorial"></a></h2>
|
|
<p>Certiorem is a PubSubHubub (PSH) implementation for ROME. It isn't an application, but an API for building each of the three components (Publisher, Subscriber and Hub) into your web apps.</p>
|
|
<p>You can see an <a class="externalLink" href="https://github.com/rometools/rome-incubator/tree/master/pubsubhubub/webapp">example webapp here</a>.</p></div>
|
|
<div class="section">
|
|
<h2>Creating a Hub<a name="Creating_a_Hub"></a></h2>
|
|
<p>Hubs take notifications, or "Pings" that tell it the content of a feed has been updated, fetch the feed, then notify each of the subscribers of the change. As you will begin to see, Certiorem is very much about "Composition" of classes. The Hub class is a prime example of this.</p>
|
|
<p>Looking at the example webapp we see:</p>
|
|
<div class="source">
|
|
<pre>@Provides
|
|
@Singleton
|
|
public Hub buildHub() {
|
|
FeedFetcher fetcher = new HttpURLFeedFetcher(new DeltaFeedInfoCache());
|
|
    Hub hub = new Hub(new InMemoryHubDAO(), new UnthreadedVerifier(), new UnthreadedNotifier(), fetcher);
|
|
|
|
    return hub;
|
|
}</pre></div>
|
|
<p>First we construct an instance of FeedFetcher, from the Fetcher subproject. This will be used to fetch feeds from remote hosts. There are a number of implementations for FeedFetcher and FeedInfoCache in the Fetcher project. Please look there for info on what is what.</p>
|
|
<p>Next we need a HubDAO implementation. This is a DAO for managing Subscriber and SubscriptionSummary classes. Here we are using an in-memory DAO, which like the HashMapFeedInfoCache will evaporate if we restart our web application. A JPA implementation for persistence is also available, but incomplete at time of writing.</p>
|
|
<p>Next we need two implementations of network client interfaces: a Verifier, and a Notifier. The Verifier calls back to the Subscribers and verifies their subscribe/unsubscribe operations. A Notifier is used to send updates to to the clients. There are two basic implementations of these provided: A ThreadPool* and Unthreaded* version of each. The thread pool version uses a ThreadPoolExecutor to run queues of outbound calls. The Unthreaded version of each, makes the network calls in-line with the request to the hub. These are suitable for environments like Google App Engine where spawning threads from servlets is absolutely verboten.</p>
|
|
<p>There are other constructors that contain lists of restrictions for what the hub will support: acceptable topic feeds, ports, protocols, etc.</p>
|
|
<p>The hub here is just a business logic class. In order to have a functioning hub, we need a servlet exposing the Hub. In the "web" package, there is an abstract servlet you can use to do just this. In the Guice wired example, we simply create a servlet with an injected Hub implementation.</p>
|
|
<div class="source">
|
|
<pre>@Singleton
|
|
public class HubServlet extends AbstractHubServlet {
|
|
|
|
@Inject
|
|
public HubServlet(final Hub hub){
|
|
super(hub);
|
|
}
|
|
}
|
|
//... in the ServerModule...
|
|
|
|
serve("/hub*").with(HubServlet.class);</pre></div>
|
|
<p>We can now include a <link rel="hub"> value in our feeds and publish notifications of changes. </p></div>
|
|
<div class="section">
|
|
<h2>Publishing Ping Notifications<a name="Publishing_Ping_Notifications"></a></h2>
|
|
<p>This is perhaps the easiest thing to do. The Publisher class will take various combinations of URLs and SyndFeeds and send the appropriate notification. If your SyndFeed contains a <link rel='sel' /> and <link rel='hub' /> you can just pass the SyndFeed object. Otherwise, you can use the URL strings where appropriate.</p>
|
|
<p>The example couldn't be simpler:</p>
|
|
<div class="source">
|
|
<pre>Publisher pub = new Publisher();
|
|
try {
|
|
pub.sendUpdateNotification("http://localhost/webapp/hub", "http://localhost/webapp/research-atom.xml");
|
|
} catch (NotificationException ex) {
|
|
Logger.getLogger(NotifyTest.class.getName()).log(Level.SEVERE, null, ex);
|
|
throw new ServletException(ex);
|
|
}</pre></div>
|
|
<p>Once this notification is sent, the hub will make a request to the feed and notify the clients of new entries.</p></div>
|
|
<div class="section">
|
|
<h2>Subscribing to Feeds<a name="Subscribing_to_Feeds"></a></h2>
|
|
<p>To set up a feed subscriber, you need to go through a process very much like setting up a Hub. First, create the Subscriptions class by composition:</p>
|
|
<div class="source">
|
|
<pre>@Provides
|
|
@Singleton
|
|
public Subscriptions buildSubs(){
|
|
    Subscriptions subs = new Subscriptions(new HashMapFeedInfoCache(), new AsyncRequester(),
|
|
            "http://localhost/webapp/subscriptions/", new InMemorySubDAO());
|
|
    return subs;
|
|
}</pre></div>
|
|
<p>First we need a FeedInfoCache implementation. This will be updated as notifications come in, so in your web app, you want to make sure this is shared with the FeedFetcher implementation you are using to read feeds. Next you need a Requester, this is a network class that makes subscription requests to remote hubs. Next, a URL prefix for where the callbacks will live. This really means the URL to the SubServlet that is resolvable externally. Finally, a DAO for storing and retrieving Subscription objects.</p>
|
|
<p>As in the Hub, we need a wrapper servlet to call into the Subscriptions class</p>
|
|
<div class="source">
|
|
<pre>@Singleton
|
|
public class SubServlet extends AbstractSubServlet {
|
|
|
|
@Inject
|
|
public SubServlet(final Subscriptions subscriptions){
|
|
super(subscriptions);
|
|
}
|
|
}
|
|
|
|
// In the ServerModule...
|
|
serve("/subscriptions/*").with(SubServlet.class)</pre></div>
|
|
<p>Now if we want to subscribe to a feed, we get a reference to the Subscriptions object, and pass in either the SyndFeed (with appropriate rel="hub" and rel="self" links) or simply a couple of URLs:</p>
|
|
<div class="source">
|
|
<pre> subs.subscribe("http://localhost/webapp/hub", "http://localhost/webapp/research-atom.xml", true, -1, null, new SubscriptionCallback(){
|
|
|
|
public void onFailure(Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
public void onSubscribe(Subscription subscribed) {
|
|
System.out.println("Subscribed "+subscribed.getId() +" "+subscribed.getSourceUrl());
|
|
}
|
|
|
|
});</pre></div>
|
|
<p>Here we pass in the URL of the Hub, the URL of the feed, a boolean indicating we want to make the subscription request synchronously, the lease seconds we want to keep the subscription for, a null cryptographic secret, and a Callback invoked when the subscribe request completes.</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr/>
|
|
|
|
<footer>
|
|
<div class="container-fluid">
|
|
<div class="row span12">Copyright © 2016.
|
|
All Rights Reserved.
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
</html>
|