<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Engineering Notebook</title>
	<atom:link href="http://engineeringnotebook.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://engineeringnotebook.org</link>
	<description>Stuff I Say</description>
	<lastBuildDate>Fri, 17 Feb 2012 16:25:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Decomposing a Service Oriented Architecture</title>
		<link>http://engineeringnotebook.org/decomposing-a-service-oriented-architecture/</link>
		<comments>http://engineeringnotebook.org/decomposing-a-service-oriented-architecture/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 02:31:08 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[SaaS]]></category>
		<category><![CDATA[service oriented architecture]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Software Architecture]]></category>
		<category><![CDATA[Web Services]]></category>
<category>SaaS</category><category>service oriented architecture</category><category>SOA</category><category>Software Architecture</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=2398</guid>
		<description><![CDATA[One of the questions I’m most frequently asked is how to go about decomposing a system into services to develop a service-oriented architecture (SOA).  To understand how to divide a system into specific services, we first need to think about what we are trying to achieve with our software architecture.  In most large development projects, experience has taught us that we rarely ever fully understand the problem we are designing for at the outset of the project.  So, first and [...]]]></description>
			<content:encoded><![CDATA[<p>One of the questions I’m most frequently asked is how to go about decomposing a system into services to develop a <a title="SOA" href="http://en.wikipedia.org/wiki/Service-oriented_architecture" target="_blank">service-oriented architecture</a> (SOA).  To understand how to divide a system into specific services, we first need to think about what we are trying to achieve with our software architecture.  In most large development projects, experience has taught us that we rarely ever fully understand the problem we are designing for at the outset of the project.  So, first and foremost, we want to design for change, because we’ll need to adapt our software design over the life of the project. Much of the software industry has embraced Agile development processes because they enable software teams to quickly adapt to their evolving understanding of requirements and design objectives.  Similarly, we have found it beneficial to embrace architecture practices that enable flexibility throughout the design lifecycle, which is a major motivation for SOAs.</p>
<p>SOA design is in many ways an extension of object-oriented (OO) design, so we can apply much of what we already know to SOA design.  Let’s start with the concepts of <a href="http://en.wikipedia.org/wiki/Coupling_(computer_programming)" target="_blank">coupling</a> and <a href="http://en.wikipedia.org/wiki/Cohesion_(computer_science)" target="_blank">cohesion</a>.</p>
<h2>Coupling</h2>
<p>It is commonly accepted in the software engineering community that loosely-coupled classes make for better OO designs, because, in general, loose coupling can minimize the scope of changes that must be made to components within the system over time and can enable component reuse. Over the past several years, new schools of thought have emerged that expand on this concept to separate some aspects of a software application&#8217;s control flow from the application&#8217;s business logic. This <a href="http://martinfowler.com/articles/injection.html" target="_blank">Inversion of Control</a> concept (aka Dependency Injection) has been embodied in the <a href="http://java.com/en/" target="_blank">Java</a> language (though annotations) and is supported by some application component frameworks (e.g. <a href="http://www.springsource.org/" target="_blank">Spring</a> and <a href="http://www.oracle.com/technetwork/java/javaee/ejb/index.html" target="_blank">EJB</a> containers). The same loose-coupling concept should be applied to services, and one key way to limit coupling is to separate <a href="http://en.wikipedia.org/wiki/Business_process" target="_blank">business process</a> workflows from business logic. Services should provide business logic, but we don’t want to bake workflows into the service logic because to do so would reduce the flexibility of the architecture. We want the option of changing the way business process workflows unfold, we want to promote reuse of business logic across multiple business processes and we want to enable our system to expand to meet new business demands, all without the need to significantly change the services.  Extracting the workflow logic into a separate “orchestration” layer enables us to do just that.</p>
<div>
<div id="attachment_2412" class="wp-caption aligncenter" style="width: 957px"><a href="http://engineeringnotebook.org/wp-content/uploads/2011/09/BusinessProcess.png"><img class="size-full wp-image-2412" title="Business Process" src="http://engineeringnotebook.org/wp-content/uploads/2011/09/BusinessProcess.png" alt="" width="947" height="338" /></a><p class="wp-caption-text">Figure 1. An example of a business process implementation where the workflow orchestration is embedded within the service logic.</p></div>
<p>Figure 1 illustrates the idea of embedding workflow orchestration into services.  Service A is the entry point for the start of a business process — assume it is invoked by a client application — and Service A then calls Services B and C in order, blocking for each response.  Service C then represents a subordinate business process, which calls and blocks for other services (D &amp; E).  The point to make from this simple diagram is that the business logic becomes intertwined with workflow if we don&#8217;t take steps to explicitly separate it.  Service A has explicit knowledge of Services B and C, and its business logic is wrapped around invocations of those services, which locks that business logic into a specific business process.  We can do better by extracting the business process orchestration into a layer above the business logic.</p>
</div>
<div>
<div id="attachment_2415" class="wp-caption aligncenter" style="width: 706px"><a href="http://engineeringnotebook.org/wp-content/uploads/2011/09/BusinessProcessOrchestration.png"><img class="size-full wp-image-2415" title="Business Process Orchestration" src="http://engineeringnotebook.org/wp-content/uploads/2011/09/BusinessProcessOrchestration.png" alt="" width="696" height="556" /></a><p class="wp-caption-text">Figure 2. An example of a business process implementation where the workflow is orchestrated by separate, specialized services.</p></div>
</div>
<p>Figure 2 illustrates an alternative approach, where we utilize separate orchestration services to create the workflow across the services, which are design to behave independently.  I&#8217;ve omitted any notion of ordering from the diagram to avoid comparison with the original workflow in Figure 1.  When workflow is omitted from the services, we must design them to operate independently around a cohesive set of business functions, which could change the invocation strategy altogether to avoid the need to manage state across transaction boundaries.  So, although there would certainly be an invocation order for the architecture illustrated in Figure 2, it would not necessarily look like the original workflow in Figure 1, and the important point is that the services should have no idea of the order in which they are invoked or of the other services in the business process.</p>
<p>Scripting grammars such as <a href="http://en.wikipedia.org/wiki/Business_Process_Execution_Language" target="_blank">BPEL</a> and <a href="http://en.wikipedia.org/wiki/BPMN" target="_blank">BPMN</a>, and supporting orchestration engines (e.g. <a href="http://ode.apache.org/" target="_blank">ODE</a>, <a href="http://www.parasoft.com/jsp/products/bpel.jsp?itemId=114" target="_blank">Maestro</a>), are commonly used to develop orchestration services such as those illustrated in Figure 2.</p>
<h2>Cohesion</h2>
<p>Just like we desire high cohesion in OO designs, we also want it in the design of services.  Each service should encapsulate a collection of strongly-related functionality, which will promote modularity, enable reuse and reduce coupling with other services.  Before we talk about how to group functions into services, it is useful to talk a bit about the different types of services that we can expect to develop in an enterprise system.  My favorite conceptual reference on this subject is the book <a href="http://www.amazon.com/Applied-SOA-Service-Oriented-Architecture-Strategies/dp/0470223650/ref=sr_1_1?ie=UTF8&amp;qid=1316395729&amp;sr=8-1" target="_blank">Applied SOA</a> [Rosen, et al.].  The authors describe a variety of different services, but the most significant are illustrated in Figure 3 below.</p>
<div id="attachment_2431" class="wp-caption aligncenter" style="width: 633px"><a href="http://engineeringnotebook.org/wp-content/uploads/2011/09/ServiceTypes.png"><img class="size-full wp-image-2431" title="ServiceTypes" src="http://engineeringnotebook.org/wp-content/uploads/2011/09/ServiceTypes.png" alt="" width="623" height="562" /></a><p class="wp-caption-text">Figure 3. Different classes of services have different levels of interface granularity.</p></div>
<p>The most significant services — and probably the most challenging to interpret — are the Business and Domain services.  The authors of <em>Applied SOA</em> define these service types in terms of granularity and accessibility.  Business services are the coarsest (encompassing the most scope) and have the broadest accessibility (enterprise wide), followed by Domain services, which are medium-grained and are limited in accessibility to support Business services inside the enterprise.</p>
<p>To understand the role of a Business service, it is illustrative to examine the public service interfaces of prominent systems, such as the <a href="http://twitter.com" target="_blank">Twitter</a> REST <a href="https://dev.twitter.com/docs/api" target="_blank">API</a>.  Twitter&#8217;s REST API constitutes the system&#8217;s publicly-exposed (enterprise) service interfaces, categorized into their major business functional areas (e.g. Tweets, Timelines, Users, Local Trends, Friends &amp; Followers, etc), so these interfaces can be considered examples of Business services, which invoke Domain and Utility services that are not publicly exposed.  For example, the basic service for <a href="https://dev.twitter.com/docs/api/1/post/statuses/update" target="_blank">updating a user’s status</a> (aka posting a tweet) involves functions such as user validation, geolocation, URI shortening, linking references to other users and hashtags, conversation threading, etc.  Some of these functions are satisfied by Domain and Utility services that are not publicly accessible.</p>
<p>The scope of Twitter&#8217;s Business services do not limit the range of potential business processes.  The independent and functional nature of Twitter&#8217;s public interfaces enables external applications to retrieve and correlate data using multiple interfaces in many different ways, which may not be possible if the services were conflated with business process logic.  The multitude of third-party Twitter clients and data analysis tools is a testament to the value of decoupling business logic from business processes.</p>
<p>Utility services and Integration services are more straightforward to understand.  Utility services in our Twitter example might be used to perform simple, reusable functions, like sorting a list of tweets or returning a human-readable city name from a lat/long.  Integration services are used to integrate legacy applications and generally provide a mediation facility between the interface technologies used in the new system and the interfaces of the legacy application.</p>
<h3>Business Process Definition</h3>
<p>So, how do we go about decomposing our system into a loosely-coupled, cohesive set of Business and Doman services?  It is important to understand that we really have two goals.  The first is to develop an understanding of our system’s business processes so that we can understand the behaviors and workflows the software must support.  Understanding the business processes is what will allow architects to identify cohesive sets of behaviors that should be aggregated into individual services.  However, our second goal is to avoid &#8220;over fitting&#8221; our architecture to our known set of business processes.  We want to continuously think about the ways in which our system might need to be extended to meet evolving business objectives.  Remember what I said at the beginning of this article &#8212; we rarely ever understand the full requirements for the end product at the outset of the project, so we need to design for change.</p>
<p>The first step in decomposing our services is to understand our known business processes, and there are established <a href="http://en.wikipedia.org/wiki/Business_process_modeling" target="_blank">Business Process Modeling</a> techniques that can help, such as <a href="http://en.wikipedia.org/wiki/Use-case_analysis" target="_blank">Use Case Analysis</a>.  Whether you call them System Engineers, Business Analysts or Product Managers, there is likely a role within your organization with responsibility for defining business processes.  Architects are key stakeholders in the business process development activity, because identifying and modeling business processes allows architects to identify cohesive sets of behaviors and to define entry points (i.e. Business services) into those behaviors to support business process orchestration.</p>
<p>Domain Modeling — described in detail in Eric Evan’s excellent book, <a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215" target="_blank">Domain-Driven Design</a> —  is another useful analysis technique for defining service scope.  Domain Modeling can be used successfully at different levels of abstraction. At the lowest level, Domain Modeling can be used by software engineers to define an object-oriented class structure that represents the entities and relationships in the business domains, and it can be used to inform the creation of a data model (e.g. XML messages, database tables) representing those same entities and relationships.  At a more abstract level, architects can use Domain Modeling to define a system&#8217;s major conceptual entities (e.g. Customer, Account, Invoice, etc) and understand their behavioral lifecycle through the various business processes, which can help to identify cohesive sets of domain entities and their behaviors that we will encapsulate within domain services.</p>
<h2>Related Topics</h2>
<p>There are a few other related topics that are worth briefly mentioning.</p>
<p><em>Data Encapsulation</em> — In my experience, it is not uncommon for software engineers to want to share data between services through a common database.  In my view, this is a bad idea and conflicts with our loose coupling goal.  Services should encapsulate their data, and access to that data should only happen through the service interface.  Software engineers will argue that this can lead to redundant data being stored in the system.  To me, redundant data should probably lead us to conclude that either the services are decomposed incorrectly, perhaps by misunderstanding the business process or domain model, or the services should not have been decomposed at all because the behaviors spread across the two services that need to share data were so cohesive that they should have been kept together.</p>
<p><em>REST vs. SOAP</em> — Much has been written about the relative virtues of <a href="http://www.amazon.com/Restful-Web-Services-Leonard-Richardson/dp/0596529260/ref=sr_1_1?ie=UTF8&amp;qid=1316489622&amp;sr=8-1" target="_blank">RESTful web services</a> and <a href="http://www.amazon.com/Java-Web-Services-Up-Running/dp/059652112X/ref=sr_1_9?s=books&amp;ie=UTF8&amp;qid=1316489743&amp;sr=1-9" target="_blank">SOAP-based (WSDL) web services</a>, so I won&#8217;t repeat all of that here.  However, in my experience, SOAP-based services are more complex to develop than RESTful services.  The creation of <a href="http://www.w3.org/TR/wsdl" target="_blank">WSDL</a>s, designing complex XML schemas, working with a web service stack (e.g. <a href="http://metro.java.net/" target="_blank">Metro</a>) and integrating the language-specific object-marshaling technologies (e.g. <a href="http://www.oracle.com/technetwork/articles/javase/index-140168.html" target="_blank">JAXB</a>) can be challenging.  There are simply more moving parts with SOAP-based services than with RESTful services.  So, in my opinion, it is better to default to RESTful services unless there is a clear and compelling need for some of the advanced capabilities offered through the <a href="http://en.wikipedia.org/wiki/List_of_web_service_specifications" target="_blank">web service specifications</a>.  However, it is worth <a href="http://wiki.apache.org/ws/StackComparison" target="_blank">verifying</a> that any given WS-* specification is supported in a variety of cross-language web service stacks (many are not), or you could be trading portability for capability.</p>
<p>I have also come to prefer RESTful web services because I feel that they abstract away more of the software architecture details from the consumers.  SOAP-based services are often described as <a href="http://en.wikipedia.org/wiki/Remote_procedure_call" target="_blank">RPC</a> services, because consumers reference specific methods on specific services through the WSDL.   With RESTful services, architects design interfaces around the concept of a resource and use standard <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol" target="_blank">HTTP</a> methods to manage operations on those resources, which can fit together nicely with Domain Modeling to help identify and organize resources.</p>
<h2>Conclusions</h2>
<p>SOA is a set of architecture concepts, not a set of enabling technologies.  It is entirely possible to adopt the technologies without realizing any of the SOA benefits (beware of systems comprised primarily of legacy software that has been SOA-ized with XML wrappers).  Above all, the way we go about decomposing our system into services is motivated by a desire to instill extensibility into our software architecture and to enable reuse so that we can reduce the cost of adapting to changing business needs.  We achieve these SOA concepts by investing in developing an understanding of a system&#8217;s business processes to identify cohesive behaviors, by enforcing a separation of business process workflows from business logic and by driving our development teams to think about and design software in terms of the system&#8217;s Domain Model.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/decomposing-a-service-oriented-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Glassfish Monitoring Client Using REST</title>
		<link>http://engineeringnotebook.org/building-a-glassfish-monitoring-client-using-rest/</link>
		<comments>http://engineeringnotebook.org/building-a-glassfish-monitoring-client-using-rest/#comments</comments>
		<pubDate>Sun, 10 Jul 2011 18:44:14 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Software Architecture]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Web Services]]></category>
<category>glassfish</category><category>jee</category><category>rest</category><category>service oriented architecture</category><category>SOA</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=2180</guid>
		<description><![CDATA[The GlassFish 3.1 Application Server provides a REST web service interface that enables service consumers to access administrative and monitoring features.  Although GlassFish&#8217;s web-based admin console is generally regarded as one of the better app server consoles, in my experience with previous versions of GlassFish, there are some cases where the web console can be difficult to use.  For example, during clustered server failover scenarios, the web console will freeze until the network connection times out, which can take a minute or two.   To allow [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://glassfish.java.net/" target="_blank">GlassFish</a> <a href="http://glassfish.java.net/downloads/3.1-final.html" target="_blank">3.1</a> Application Server provides a <a href="http://download.oracle.com/docs/cd/E18930_01/html/821-2416/gjipx.html" target="_blank">REST web service interface</a> that enables service consumers to access administrative and monitoring features.  Although GlassFish&#8217;s web-based admin console is generally regarded as one of the better app server consoles, in my experience with previous versions of GlassFish, there are some cases where the web console can be difficult to use.  For example, during clustered server failover scenarios, the web console will freeze until the network connection times out, which can take a minute or two.   To allow more control over the client-side response to server admin events, I&#8217;ve recently started a side project to develop a client-side Java API to the GlassFish REST admin interface.  The API is decoupled from a user interface and is intended to be utilized by a UI developer, but could also be used by any consumer application that needs GlassFish server status.</p>
<p>The scope of the GlassFish REST interface can be explored through the <a href="http://en.wikipedia.org/wiki/Web_Application_Description_Language" target="_blank">WADL</a> file available from the GlassFish server.  There are two WADL files, one for the Management resources and another for the Monitoring resources.  The URIs for the WADL files follow below.</p>
<p><em>Management REST resources</em>: <span style="color: #3366ff;">http://serverURL:4848/management/application.wadl</span><br />
<em>Monitoring REST resources</em>: <span style="color: #3366ff;">http://serverURL:4848/monitoring/application.wadl</span></p>
<p>Using the URIs above, just point your browser to your GlassFish installation and the WADL files will be returned.  The Management WADL file is large, so it may take a while to load.  For a detailed description of the WADL schema, check out the W3C <a href="http://www.w3.org/Submission/wadl/" target="_blank">specification</a>.</p>
<p>Despite what the names of the REST interfaces might lead you to believe, I&#8217;ve developed all of the features of the monitoring API library using the Management REST resources.  The Monitoring resources seem to be undeveloped, unless I am not interpreting the sparse WADL file correctly.  Either way, the Management resources provide all of the necessary capability.  Listing 1 below illustrates a small portion of the Management WADL file.</p>
<p style="text-align: center;"><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Listing 1: Partial WADL file detailing the available Management REST resources.</span></p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
&lt;application xmlns="http://research.sun.com/wadl/2006/10"&gt;
    &lt;doc xmlns:jersey="http://jersey.dev.java.net/" jersey:generatedBy="Jersey: 1.5 01/14/2011 12:36 PM"/&gt;
    &lt;resources base="http://localhost:4848/management/"&gt;

&lt;!-- snip snip --&gt;

      &lt;resource path="clusters/"&gt;

&lt;!-- snip snip --&gt;

          &lt;resource path="list-clusters/"&gt;
              &lt;method id="processGet" name="GET"&gt;
                  &lt;response&gt;
                      &lt;representation mediaType="text/html;qs=2"/&gt;
                      &lt;representation mediaType="application/json"/&gt;
                      &lt;representation mediaType="application/xml"/&gt;
                      &lt;representation mediaType="application/x-www-form-urlencoded"/&gt;
                  &lt;/response&gt;
              &lt;/method&gt;
              &lt;method id="options" name="OPTIONS"&gt;
                  &lt;response&gt;
                      &lt;representation mediaType="text/html;qs=2"/&gt;
                      &lt;representation mediaType="application/json"/&gt;
                      &lt;representation mediaType="application/xml"/&gt;
                  &lt;/response&gt;
              &lt;/method&gt;
           &lt;/resource&gt;
      &lt;/resource&gt;

&lt;!-- snip snip --&gt;

  &lt;/resources&gt;
&lt;/application&gt;</pre>
<p>As you can see from Listing 1, the <em>list-clusters</em> resource is accessed through the HTTP GET method at the URI <em>http://localhost:4848/management/domain/clusters/list-clusters</em> and supports four different response types.  I have used the <a href="http://jersey.java.net/" target="_blank">Jersey</a> REST client-side API for all of the REST calls in the GlassFish Monitoring API library, which conveniently abstracts away the details of forming valid HTTP calls.</p>
<p>Before I begin to describe the GlassFish Monitoring API software, let me be clear that this is a very early prototype, largely intended to flesh out the concepts.  I&#8217;ve started small with code to monitor clusters and their member instances, and the status data is simply written to the log &#8212; no GUI yet.  It is reasonable to conclude that there will be some restructuring of the software as I tie the API into a user interface and expand the scope to monitor more aspects of the GlassFish server.</p>
<p>Figure 1 below illustrates the top-level package structure for the GlassFish Monitoring API.  The <em>client</em> package contains a sample client that starts up the monitoring and status threads (more on that below).  As you might expect, the <em>cluster</em> and <em>instance</em> packages contain the classes for monitoring clusters and their instances.  The <em>status</em> package contains interfaces that are implemented by classes representing a a status monitor, a server status message and a DOM parser for XML status data.  The <em>util</em> package contains a few odds and ends, primarily for initializing pretty-printing XML responses from the server and to manage a configuration properties map that is built from an XML config file.</p>
<div id="attachment_2211" class="wp-caption aligncenter" style="width: 994px"><a href="http://engineeringnotebook.org/wp-content/uploads/2011/07/packages.png"><img class="size-full wp-image-2211  " title="packages" src="http://engineeringnotebook.org/wp-content/uploads/2011/07/packages.png" alt="" width="984" height="408" /></a><p class="wp-caption-text">Figure 1. Top-level package structure for GlassFish Monitor Client API.</p></div>
<p>Figure 1 also depicts two interfaces &#8212; Subject and Observer.  As the names imply, these interfaces are implemented by classes that utilize the <a href="http://en.wikipedia.org/wiki/Design_Patterns_(book)" target="_blank">GoF</a> <a title="Observer Pattern" href="http://en.wikipedia.org/wiki/Observer_pattern" target="_blank">Observer pattern</a>, which is central to the organization of this API.</p>
<p>Figure 2 illustrates the class implementation (within the <em>cluster</em> package) of the ClusterListMonitor (subject) and ClusterListStatusObserver (observer).  Status monitoring and status reporting are separated into two different threads.  Monitoring classes, which implement both the <em>StatusMonitor</em> and <em>Subject</em> interfaces, run in their own thread and are responsible for polling the GlassFish server for the status of a specific item of interest (e.g. clusters).  Status observer classes implement the <em>Observer</em> interface, and they also run in their own thread.  Status observer classes are responsible for providing a response to the status reported by the monitor.  Responses could include updating a graphical user interface, writing to a log file or executing some predefined rule.</p>
<div id="attachment_2329" class="wp-caption aligncenter" style="width: 1173px"><a href="http://engineeringnotebook.org/wp-content/uploads/2011/07/cluster_class22.png"><img class="size-full wp-image-2329 " title="cluster_class2" src="http://engineeringnotebook.org/wp-content/uploads/2011/07/cluster_class22.png" alt="" width="1163" height="422" /></a><p class="wp-caption-text">Figure 2. Class implementation to monitor and report cluster status data.</p></div>
<p>I had some concern about the overhead of using two threads for each unique monitored item, but ultimately thought the benefits justified the overhead.  One of those benefits is the ability to establish a wait time for the status observer thread, which decouples it from the blocking status request of the monitoring thread.  If the status monitoring thread is blocking for an unresponsive server, the status observer thread can abort the wait for a status update and take some alternative action, such as update a user interface component for a monitored item to denote the &#8220;unresponsive&#8221; status.  The ability to have this type of control over blocking status requests was one of my primary motives for developing this API.  With previous versions of GlassFish, one could only watch impatiently as the admin web console froze until the network connection to a failed server timed out.  I expect the monitoring and observer threads to manage fairly coarse-grained server items, such as the set of all clusters monitored by the classes in Figure 2, so I don&#8217;t envision more than a dozen or so unique monitored items, which would keep the number of threads acceptably low.  The instance monitor and observer classes, in the <em>instance</em> package, are structured similarly to the cluster classes in Figure 2.</p>
<p>Figure 3 depicts the interaction between the Monitor and Observer threads described above.</p>
<div id="attachment_2226" class="wp-caption aligncenter" style="width: 828px"><a href="http://engineeringnotebook.org/wp-content/uploads/2011/07/ClusterSequence.png"><img class="size-full wp-image-2226" title="ClusterSequence" src="http://engineeringnotebook.org/wp-content/uploads/2011/07/ClusterSequence.png" alt="" width="818" height="376" /></a><p class="wp-caption-text">Figure 3. The monitor (subject) and observer run in separate threads.</p></div>
<p>The thread loop (<em>run </em>method) and the REST operation (<em>queryStatusOfClusters </em>method) for the <a href="https://github.com/jeffcoble/GlassFishMonitor/blob/master/src/main/java/org/engineeringnotebook/glassfishmonitor/cluster/ClusterListMonitor.java" target="_blank">ClusterListMonitor</a> class are depicted in Listing 2 below.  The <em>run</em> method is simple &#8212; query the GlassFish server for status and notify the observers, then sleep for the user-specified time.  The REST operation is performed using the <a href="http://jersey.java.net/" target="_blank">Jersey</a> API to construct the GET operation and specify the response type, then the operation is executed on the GlassFish server and the XML response is passed back to be parsed.  See the <a href="https://github.com/jeffcoble/GlassFishMonitor/blob/master/src/main/java/org/engineeringnotebook/glassfishmonitor/cluster/ClusterListMonitor.java" target="_blank">full listing</a> for all of the gory details.</p>
<p style="text-align: center;"><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Listing 2: Some salient portions of the <a href="https://github.com/jeffcoble/GlassFishMonitor/blob/master/src/main/java/org/engineeringnotebook/glassfishmonitor/cluster/ClusterListMonitor.java" target="_blank">ClusterListMonitor</a> class.</span></p>
<pre class="brush: java; gutter: true; first-line: 1">//snip snip

public class ClusterListMonitor implements StatusMonitor, Subject, Runnable {

//snip snip

public void run() {
   while(true) {
      //query the GF rest interface for the cluster status
      clusterStatusList = this.queryGFStatus();
      //notify the observers of the new status
      notifyObservers(clusterStatusList);
      //sleeping for the user-specified polling rate
      try {
         Thread.sleep(pollingRate);
      } catch(InterruptedException ie) {
          logger.log(Level.INFO, "Cluster Monitor Thread Problem: {0}", new Object[]{ie});
      }
   }
}

//snip snip

/**
 * Poll the server for status and parse the XML response
 *
 * @return The status reported by the GF server
 */
public ArrayList&lt;Status&gt; queryGFStatus() {
    ArrayList&lt;Status&gt; statusList = null;

    if(restClient != null) {
        String response = queryStatusOfClusters(restClient);
        if(response != null)
          statusList = parseClusterStatusResponse(response);
    }

    return statusList;
}

/**
 * Performs the GET operation on http://baseURL/management/domain/clusters/list-clusters
 *
 * @param client The Jersey rest client
 *
 * @return The XML text
 */
private String queryStatusOfClusters(Client client) {

   //Construct the resource and perform the GET operation
   WebResource webResource = client.resource(restURL);
   ClientResponse response = webResource.accept("application/xml").get(ClientResponse.class);

   int status = response.getStatus();
   logger.log(Level.FINEST, "list-clusters Status =  {0}", new Object[]{status});

   String textEntity = response.getEntity(String.class);
   if(textEntity != null) {
      logger.log(Level.FINEST, "list-clusters Response =  {0}", new Object[]{textEntity});
      StatusUtilities.writeResponseToFile(textEntity, "cluster-status.xml");
   }
   else
      logger.log(Level.FINEST, "list-clusters Response =  No Clusters");

   return textEntity;
}

//snip snip

}</pre>
<p>Listing 3 below illustrates a sample config.xml file, which allows the user to configure the base URL for the GlassFish REST interface, the status polling rate and the observer wait time. The config.xml file resides at the root of the JAR file.</p>
<p style="text-align: center;"><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Listing 3: XML config file allows users to specify configuration properities.</span></p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;?xml version="1.0" encoding="UTF-8"?&gt;

&lt;config&gt;
  &lt;baseURL&gt;http://localhost:4848&lt;/baseURL&gt;
  &lt;pollingrate&gt;5000&lt;/pollingrate&gt;
  &lt;responsewaittime&gt;10000&lt;/responsewaittime&gt;
&lt;/config&gt;</pre>
<p>Once I&#8217;ve expanded the scope of the API library, I expect to provide individual configuration properties for each monitored item.  So, for example, the polling rate could be set differently for each monitor thread.</p>
<h4>Conclusion</h4>
<p>As I mentioned above, this is an early prototype of the API software, and there are still several design concepts that I&#8217;m thinking through, but I wanted to get it out there so I could return to my <a href="http://engineeringnotebook.org/project-overview/" target="_blank">primary project</a> &#8211; so caveat emptor.  I&#8217;ll continue to provide updates to this library over time, but for now it will be moving to the back burner.  Feel free to <a href="mailto:jeffrey.a.coble@gmail.com">contact me</a> if you have any questions.  Have fun!</p>
<h4><strong>Resources</strong></h4>
<ul>
<li>The <a href="https://github.com/jeffcoble/GlassFishMonitor" target="_blank">source code</a> for the GlassFish Monitoring API library is available at <a href="http://github.com" target="_blank">GitHub</a>.  The source is released under the <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License, Version 2.0</a>.</li>
<li>The GlassFish Monitoring API library <a href="http://engineeringnotebook.org/wp-content/glassfishmonitor/apidocs/" target="_blank">JavaDocs</a> (still a bit rough).</li>
<li>The GlassFish REST Admin API <a href="http://download.oracle.com/docs/cd/E18930_01/html/821-2416/gjipx.html" target="_blank">documentation</a>.</li>
<li><a href="http://blogs.steeplesoft.com/2010/08/glassfish-administration-the-rest-of-the-story/" target="_blank">Here</a> and <a href="http://blogs.steeplesoft.com/2010/12/glassfish-administration-the-rest-of-the-story-part-ii-deploying-apps-using-scala/" target="_blank">here</a> are a couple of blog entries that provide some introductory information about the GlassFish REST Admin API.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/building-a-glassfish-monitoring-client-using-rest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EJB, JPA and SimpleDB in &#8220;The Cloud&#8221;</title>
		<link>http://engineeringnotebook.org/ejb-jpa-simpledb-cloud/</link>
		<comments>http://engineeringnotebook.org/ejb-jpa-simpledb-cloud/#comments</comments>
		<pubDate>Sun, 20 Mar 2011 22:59:41 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[Web Services]]></category>
<category>Amazon</category><category>cloud computing</category><category>EJB</category><category>JPA</category><category>oauth</category><category>restful</category><category>Social Networking</category><category>Twitter</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1898</guid>
		<description><![CDATA[As part of my personal project, I&#8217;ve been working on some basic plumbing web services to support data access.  The first of these two web services &#8212; the Registration Service &#8212; allows a user to authorize my application to retrieve protected resources on behalf of the user.  The second of the services &#8212; the Resource Manager Service &#8212; simply uses the access granted by the user to retrieve a user&#8217;s protected resource.  Together, these two services provide the initial foundation [...]]]></description>
			<content:encoded><![CDATA[<p>As part of my <a href="http://engineeringnotebook.org/project-overview/" target="_blank">personal project</a>, I&#8217;ve been working on some basic plumbing web services to support data access.  The first of these two web services &#8212; the <a title="GitHub Project" href="https://github.com/jeffcoble/RegistrationServiceProject" target="_blank">Registration Service</a> &#8212; allows a user to authorize my application to retrieve protected resources on behalf of the user.  The second of the services &#8212; the <a title="GitHub Project" href="https://github.com/jeffcoble/ResourceManagerServiceProject" target="_blank">Resource Manager Service</a> &#8212; simply uses the access granted by the user to retrieve a user&#8217;s protected resource.  Together, these two services provide the initial foundation I&#8217;ll be using to enable my data mining software to access a user&#8217;s social networking data and mine for patterns.  Initially, I&#8217;ve developed these services to work with <a title="Twitter" href="http://twitter.com" target="_blank">Twitter</a> &#8212; for no other reason other than I was more familiar Twitter&#8217;s REST API &#8212; but I will soon add support for <a title="Facebook" href="http://www.facebook.com" target="_blank">Facebook</a> and <a title="LinkedIn" href="http://www.linkedin.com" target="_blank">LinkedIn</a>.</p>
<p>Each of the services follows the same, simple design approach.  The RESTful resource is exposed using Sun’s <a href="http://jersey.java.net/" target="_blank">Jersey API</a> through a servlet adaptor, and the business logic is provided by a backing stateless EJB.  The EJB&#8217;s business logic for both services interacts with Twitter&#8217;s REST API (using <a href="https://github.com/fernandezpablo85/scribe-java" target="_blank">Scribe</a>) to exercise the oauth workflow and interacts with Amazon&#8217;s <a href="http://aws.amazon.com/simpledb/" target="_blank">SimpleDB</a> REST API to persist and retrieve user credential data in Amazon&#8217;s <a href="http://aws.amazon.com/" target="_blank">cloud</a>.</p>
<p><span style="font-size: medium; color: #4682b4;"><strong>Registration Service</strong></span></p>
<p>The sequence diagram below illustrates the basic control flow of the Registration Service.</p>
<div id="attachment_1972" class="wp-caption aligncenter" style="width: 564px"><a href="http://engineeringnotebook.org/wp-content/uploads/2011/03/RegistrationService.png"><img class="size-full wp-image-1972" title="RegistrationService" src="http://engineeringnotebook.org/wp-content/uploads/2011/03/RegistrationService.png" alt="" width="554" height="570" /></a><p class="wp-caption-text">Figure 1.  Registration Service Control Flow</p></div>
<p>&nbsp;</p>
<p>Step 1: The interaction starts when a client accesses the service with a Restful web service request (GET): http://base-url/register?screenname=<em>twitterScreenName</em></p>
<p>Step 2:  The Registration Service utilizes the <a href="https://github.com/fernandezpablo85/scribe-java" target="_blank">Scribe</a> <a href="http://oauth.net/" target="_blank">OAuth</a> library to get a request token from Twitter, using the keys that have been previously establish for the requesting Twitter client.</p>
<p>Steps 3 &amp; 4: Once the request token has been retrieved from Twitter, it is associated with the Twitter screen name in a <a href="https://github.com/jeffcoble/SNRDMProject/blob/master/SNRDMEntities/src/main/java/org/engineeringnotebook/snrdm/entity/UserCredential.java" target="_blank">user credential</a> object and stored in Amazon&#8217;s SimpleDB.</p>
<p>Steps 5 &amp; 6:  The Twitter authorization url is created using the oauth request token, which is then returned to the invoking client (out-of-band method).</p>
<p>Steps 7, 8 &amp; 9: The user must independently (hence the out-of-band) use the authorization url to retrieve the oauth verification token from Twitter, which is then provided back to the Registration Service using the following RESTful invocation (POST):  http://base-url/register/settoken?screenname=<em>twitterScreenName</em>&amp;token=<em>verificationToken</em></p>
<p>Listing 1 below illustrates the client&#8217;s entry point into the Registration Service, which is a resource class hosted in the web container with a servlet adaptor.  For this service, the resource class exposes two methods via RESTful web service interfaces.  The <em>getAuthorizationURL</em> method provides the entry point for the user to begin the registration process, and the <em>setVerificationToken</em> method allows the user to provide the verification token back to the service as part of the OAuth process.</p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Listing 1 (<a href="https://github.com/jeffcoble/RegistrationServiceProject/blob/master/RegistrationService-web/src/main/java/org/engineeringnotebook/registrationservice/resource/RegistrationResource.java" target="_blank">org.engineeringnotebook.registrationservice.resource.RegistrationResource</a>):</span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//snip snip</span>
@Produces<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;text/plain&quot;</span><span style="color: #009900;">&#41;</span>
@Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/register&quot;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> RegistrationResource <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//snip snip</span>
&nbsp;
    @GET
    @Produces<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;text/plain&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getAuthorizationURL<span style="color: #009900;">&#40;</span>@QueryParam<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;screenname&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #003399;">String</span> twitterScreenName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       logger.<span style="color: #006633;">log</span><span style="color: #009900;">&#40;</span>Level.<span style="color: #006633;">FINE</span>, <span style="color: #0000ff;">&quot;Registration resource: getAuthorizationURL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       <span style="color: #003399;">String</span> result <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
       <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>twitterScreenName <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
          connectEJB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
          result <span style="color: #339933;">=</span> registrationServiceEJB.<span style="color: #006633;">requestRegistration</span><span style="color: #009900;">&#40;</span>twitterScreenName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       <span style="color: #009900;">&#125;</span>
       <span style="color: #000000; font-weight: bold;">return</span> result<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//snip snip</span>
&nbsp;
    @POST
    @Consumes<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;text/plain&quot;</span><span style="color: #009900;">&#41;</span>   
    @Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/settoken&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">public</span> Response setVerificationToken<span style="color: #009900;">&#40;</span>@QueryParam<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;screenname&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #003399;">String</span> twitterScreenName, @QueryParam<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;token&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #003399;">String</span> verificationToken<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        logger.<span style="color: #006633;">log</span><span style="color: #009900;">&#40;</span>Level.<span style="color: #006633;">FINE</span>, <span style="color: #0000ff;">&quot;Registration resource: setVerificationToken&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        URI uri <span style="color: #339933;">=</span>  uriInfo.<span style="color: #006633;">getAbsolutePath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>twitterScreenName <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            connectEJB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            registrationServiceEJB.<span style="color: #006633;">setVerificationToken</span><span style="color: #009900;">&#40;</span>twitterScreenName, verificationToken<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>  
        <span style="color: #666666; font-style: italic;">//need to figure out how to set the response if input parms are invalid</span>
        <span style="color: #000000; font-weight: bold;">return</span> Response.<span style="color: #006633;">created</span><span style="color: #009900;">&#40;</span>uri<span style="color: #009900;">&#41;</span>.<span style="color: #006633;">build</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> 
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Line 3 is an annotation enabled by Jersey and defines the base path for the service.  Line 8 associates the HTTP GET operation with the specific method, and line 9 defines the content MIME type that can be consumed by the method.  The @QueryParam annotation on line 10 associates a query parameter from the URL string with a specific method parameter.  Line 15 invokes the backing EJB, which provides the business logic.  I prefer to cleanly separate the web service interface from the business logic, and I feel that hosting the interface in the web container separate from the business logic is a good way to enforce that pattern.</p>
<p><span style="font-size: medium; color: #4682b4;"><strong>JPA and SimpleDB</strong></span></p>
<p>As part of this project, I wanted to utilize the <a href="http://www.oracle.com/technetwork/java/javaee/tech/persistence-jsp-140049.html" target="_blank">Java Persistence API</a> (JPA) to manage data in Amazon&#8217;s SimpleDB, since JPA is the standard Java mechanism for object-relational mapping of POJOs.  <a href="http://code.google.com/p/simplejpa/" target="_blank">SimpleJPA</a> is the only JPA implementation for Amazon&#8217;s SimpleDB that I could find with any significant user base, so that&#8217;s what I&#8217;ve used in my two services to persist the user credential POJOs.  There were a few challenges that I had to overcome with SimpleJPA.  The first challenge was my own ignorance about how JPA works with respect to needing corresponding getter and setter methods in the entity classes to persist and instantiate objects.  I burned a few cycles trying to figure out why my objects weren&#8217;t being instantiated only to find out I was missing some corresponding setter methods.  Don&#8217;t do that!  :)</p>
<p>The biggest challenge I had with SimpleJPA was overcoming the way in which it finds entities to manage.  According to the <a href="http://jcp.org/en/jsr/detail?id=317">JPA2 spec</a>, one should be able to define the persistence unit and specify the fully qualified entity class names in the <em>persistence.xml</em> file, which would then be picked up by the JPA implementation at run-time.  However, in all of my tests, SimpleJPA seemed to ignore everything specified in this file.  In Listing 2 below you can see where I identified the UserCredential class on line 5 in my <em>persistence.xml</em> file, which had no affect on SimpleJPA.</p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Listing 2 (persistence.xml):</span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;persistence</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://java.sun.com/xml/ns/persistence&quot;</span> <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span> <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;persistence-unit</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;RGSPersistenceUnit&quot;</span> <span style="color: #000066;">transaction-type</span>=<span style="color: #ff0000;">&quot;JTA&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;provider<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.spaceprogram.simplejpa.PersistenceProviderImpl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/provider<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.engineeringnotebook.snrdm.entity.UserCredential<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/persistence-unit<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/persistence<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>So, instead of relying on the <em>persistence.xml</em> file to define the persistence unit, I had to utilize SimpleJPA&#8217;s EntityManagerFactory&#8217;s constructor to specify the entity classes.  With this approach, SimpleJPA requires the absolute path for the entity classes, so I wrote some code to construct the absolute path, which you can find <a href="https://github.com/jeffcoble/SNRDMProject/blob/master/SNRDMCore/src/main/java/org/engineeringnotebook/snrdm/core/utilities/ClassPathBuilder.java">here</a>.  For the record, I feel this is a kludge when writing code for a JEE container-managed environment.  It is generally considered bad form to reach outside of the container&#8217;s sandbox &#8212; one should instead rely on the relative paths internal to the JAR file &#8212; but after trying every permutation I could conceive of to get SimpleJPA to search relative paths, the absolute path approach was the only option that worked.  I question the portability of this method, and I&#8217;ve only tested in <a href="http://glassfish.java.net/" target="_blank">Glassfish</a> 3.1, so other app servers may complain about the absolute path references.  If anyone has found a more EJB-friendly way to use SimpleJPA, please <a href="mailto: jeffrey.a.coble@gmail.com">share</a> your insights.</p>
<p>Listing 3 illustrates the SimpleJPA setup process.  Lines 12 and 13 rely on properties that have been injected from the EJB descriptor file (<a href="https://github.com/jeffcoble/RegistrationServiceProject/blob/master/RegistrationService-ejb/src/main/resources/META-INF/ejb-jar.xml">ejb-jar.xml</a>) to provide SimpleJPA with the keys to access an Amazon account.  You&#8217;ll have to set those up for yourself and add the values to the descriptor file.  Line 9 defines the list of entity classes that we want SimpleJPA to manage, and line 15 creates the absolute path for those classes, which is passed into the SimpleJPA&#8217;s EntityManagerFactoryImpl constructor along with the keys and the name of my persistence unit.</p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Listing 3 (from <a href="https://github.com/jeffcoble/RegistrationServiceProject/blob/master/RegistrationService-ejb/src/main/java/org/engineeringnotebook/registrationservice/ejb/RegistrationServiceBeanImpl.java">org.engineeringnotebook.registrationservice.ejb.RegistrationServiceBeanImpl</a>):</span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">   <span style="color: #008000; font-style: italic; font-weight: bold;">/**
     * Sets up the simplejpa entity manager
     */</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> initializeSimpleJPA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        List<span style="color: #339933;">&lt;</span>Class<span style="color: #339933;">&gt;</span> classList <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ClassPathBuilder cpBuilder <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClassPathBuilder<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        classList.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>UserCredential.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        Map<span style="color: #339933;">&lt;</span>String,String<span style="color: #339933;">&gt;</span> props <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashMap<span style="color: #339933;">&lt;</span>String,String<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        props.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;accessKey&quot;</span>,amazonAccessKeyValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        props.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;secretKey&quot;</span>,amazonSecretKeyValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        Set<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span> libPaths <span style="color: #339933;">=</span> cpBuilder.<span style="color: #006633;">getScanPaths</span><span style="color: #009900;">&#40;</span>classList<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        factory <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> EntityManagerFactoryImpl<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;RGSPersistenceUnit&quot;</span>, props, libPaths<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><span style="font-size: medium; color: #4682b4;"><strong>Resource Manager Service</strong></span></p>
<p>The Resource Manager Service is very simple, and the basic structure of the code is the same as the Registration Service.  The Resource Manager Service allows an application to retrieve a protected resource once a user has authorized the application using the Registration Service.  Caveat Emptor!!  You would never want to expose this service to the world.  Anyone invoking this service would have access to a user&#8217;s protected resources.  This service is intended to be used within the security environment of the application the user has authorized.</p>
<p>The sequence diagram below illustrates the control flow of the Resource Manager Service.</p>
<div class="wp-caption aligncenter" style="width: 603px"><img src="http://engineeringnotebook.org/wp-content/uploads/2011/03/ResourceManagerService1.png" alt="" width="593" height="380" /><p class="wp-caption-text">Figure 2.  Resource Manager Service Control Flow</p></div>
<p>Step 1: The interaction starts when a client accesses the service with a RESTful web service request (GET): http://base-url/retrieve?screenname=<em>twitterScreenName</em>&#038;twitterurl=<em>protectedResource</em></p>
<p>Steps 2 &#038; 3:  The service retrieves the user credential from Amazon&#8217;s SimpleDB.</p>
<p>Steps 4, 5 &#038; 6: The services uses the Scribe OAuth library to sign the request and retrieve the protected resource from Twitter.</p>
<p>Step 7: The service returns the protected resource to the client.</p>
<p><span style="font-size: medium; color: #4682b4;"><strong>Conclusion</strong></span></p>
<p>That&#8217;s it!  I&#8217;ll post more information soon about the build and deployment processes for these two services, since there are some <a href="http://maven.apache.org/" target="_blank">Maven</a> dependency issues.  Now that I&#8217;ve finished the basic data access plumbing, I&#8217;m moving on to the data mining work &#8212; the fun part.  My next step is to review Amazon&#8217;s <a href="http://aws.amazon.com/elasticmapreduce/" target="_blank">Elastic MapReduce</a> service (built on <a href="http://hadoop.apache.org/" target="_blank">Hadoop</a>) for its applicability to the data mining algorithm that I plan to use initially.</p>
<p><span style="font-size: medium; color: #4682b4;"><strong>The Code</strong></span></p>
<p>All of my code is available at <a href="https://github.com/">GitHub</a> and is released under the <a href="http://www.apache.org/licenses/LICENSE-2.0.html" target="_blank">Apache 2.0 open source license</a>.  You can browse through the POM files to get an understanding of how to build the projects, but I&#8217;ll write more about that soon.  </p>
<p><a href="https://github.com/jeffcoble/RegistrationServiceProject" target="_blank">Registration Service</a></p>
<p><a href="https://github.com/jeffcoble/ResourceManagerServiceProject" target="_blank">Resource Manager Service</a></p>
<p><a href="https://github.com/jeffcoble/SNRDMProject" target="_blank">SNRDM</a> (common dependency)</p>
<p>SimpleJPA is a bit of a hassle to build because it doesn&#8217;t package up all of its dependencies, so you&#8217;ll have to manage them yourself.  I believe some of them can be found in public Maven repositories, but I can&#8217;t remember which ones.  Listing 4 below is cut from one of my POM files and includes all of SimpleJPA&#8217;s dependencies.  When you try to build, whichever of these dependencies is not found in the public Maven repositories will have to be manually added to your local Maven repo.  The SimpleJPA <a href="http://code.google.com/p/simplejpa/wiki/GettingStarted" target="_blank">wiki</a> has more information on the dependencies, but lacks the version number information.  You&#8217;ll need to use the version numbers specified in my POM files.    </p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Listing 4 (from the <a href="https://github.com/jeffcoble/RegistrationServiceProject/blob/master/RegistrationService-ejb/pom.xml">pom.xml</a> file for the Registration Service EJB):</span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- JPA Dependencies --&gt;</span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>asm<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>asm<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3.3.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>aws<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>aws-java-sdk<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.1.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>cglib<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>cglib-nodep<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-codec<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.4<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-collections<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3.2.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-lang<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-logging<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.1.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-logging-adapators<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.1.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>commons-logging-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.1.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>ehcache<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>ehcache-core<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.3.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>ehcache<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>ehcache-terracotta<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.3.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>ejb3-persistence<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>ejb3-persistence<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.httpcomponents<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>httpclient<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>kitty-cache<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>kitty-cache<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>scannotation<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>scannotation<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>slf4j<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>slf4j-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.5.11<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>slf4j<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>slf4j-jdk14<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.5.11<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javassist<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javassist<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3.14.0.GA<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Feel free to <a href="mailto: jeffrey.a.coble@gmail.com">contact me</a> if you have questions about the code.</p>
<p><span style="font-size: medium; color: #4682b4;"><strong>Background Reading</strong></span></p>
<p>A good overview of <a href="http://www.ibm.com/developerworks/java/library/j-javadev2-9/index.html" target="_blank">SimpleDB</a> and <a href="http://www.ibm.com/developerworks/java/library/j-javadev2-10.html" target="_blank">SimpleJPA</a>.</p>
<p>Amazon&#8217;s <a href="http://aws.amazon.com/simpledb/" target="_blank">SimpleDB site</a>.</p>
<p><a href="http://jersey.java.net/" target="_blank">Jersey API</a> &#8212; Oracle&#8217;s site for Jersey.</p>
<p><a href="https://github.com/fernandezpablo85/scribe-java">Scribe</a> &#8212; An awesome OAuth library.</p>
<p><span style="font-size: medium; color: #4682b4;"><strong>Development Tools</strong></span></p>
<p><a href="http://code.google.com/p/rest-client/" target="_blank">REST Client</a> &#8212; You&#8217;ll need a REST client to test any REST interactions other than GET operations.  <a href="http://code.google.com/p/rest-client/" target="_blank">This</a> one has worked well for me.</p>
<p><a href="http://code.google.com/p/t-437/" target="_blank">T-437</a> &#8212; A SimpleDB GUI Client, which you&#8217;ll want to use to verify that your data is stored as you expected.</p>
<p><a href="http://www.syntevo.com/smartgit/index.html" target="_blank">SmartGit</a> &#8212; A nice client GUI to help navigate <a href="http://git-scm.com/">Git</a>, which is especially useful if you&#8217;re a newbie to Git like me.</p>
<p><span style="font-size: medium; color: #4682b4;"><strong>To Do List</strong></span></p>
<p>The <a href="https://github.com/jeffcoble/SNRDMProject/blob/master/SNRDMEntities/src/main/java/org/engineeringnotebook/snrdm/entity/UserCredential.java" target="_blank">UserCredential</a> entity class is crudely structured to simplify my JPA testing and should be broken apart, after which key relationships between the classes will have to be defined for persistence purposes.</p>
<p>I&#8217;m using the old school JNDI method for retrieving a reference to my EJBs.  I need to update to the Dependency Injection method.</p>
<p>It is likely that my software design isn&#8217;t as faithful to the REST concepts as it could be, so I&#8217;ll be taking a fresh look at ways to be more RESTful as I continue along with my project.</p>
<p>You are welcome to <a href="mailto: jeffrey.a.coble@gmail.com">add your suggestions</a> to the list.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/ejb-jpa-simpledb-cloud/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 Ways To Improve Netflix</title>
		<link>http://engineeringnotebook.org/5-ways-to-improve-netflix/</link>
		<comments>http://engineeringnotebook.org/5-ways-to-improve-netflix/#comments</comments>
		<pubDate>Mon, 03 Jan 2011 05:18:15 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[SaaS]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Web Services]]></category>
<category>apple</category><category>Facebook</category><category>linux</category><category>netflix</category><category>ping</category><category>Social Networking</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1786</guid>
		<description><![CDATA[I am an avid user of Netflix&#8216;s &#8220;Watch Instantly&#8221; feature, but I believe Netflix is a market leader in danger of becoming a follower.  For a cautionary tale, revisit the history of digital music and the role of Napster.  Digital music is now ubiquitous, but Napster, the pioneer who initiated the online distribution trend and wrestled the distribution monopoly away from the brick and mortar music industry, no longer has a significant role in the distribution medium it created.  We&#8217;re now on [...]]]></description>
			<content:encoded><![CDATA[<p>I am an avid user of <a href="http://www.netflix.com" target="_blank">Netflix</a>&#8216;s &#8220;Watch Instantly&#8221; feature, but I believe Netflix is a market <a href="http://www.nytimes.com/2010/11/25/business/25netflix.html" target="_blank">leader</a> in danger of becoming a follower.  For a cautionary tale, revisit the history of digital music and the role of <a href="http://www.napster.com/" target="_blank">Napster</a>.  Digital music is now ubiquitous, but Napster, the pioneer who initiated the online distribution trend and wrestled the distribution monopoly away from the brick and mortar music industry, no longer has a significant role in the distribution medium it created.  We&#8217;re now on the brink of a similar revolution in digital video distribution.  All of the technology barriers to delivering content directly over the Internet to our personal devices are gone.  Services such as <a href="http://www.netflix.com" target="_blank">Netflix</a> and <a href="http://www.hulu.com" target="_blank">Hulu</a> already provide the distribution capability and there are many competing set-top boxes, like the <a href="http://us.playstation.com/" target="_blank">Playstation</a>, <a href="http://www.xbox.com/" target="_blank">Xbox</a>, <a href="http://www.apple.com/appletv/" target="_blank">Apple TV</a>, <a href="http://www.google.com/tv/" target="_blank">Google TV</a>, <a href="http://www.boxee.tv/" target="_blank">Boxee</a>, etc., to bridge the last ten feet to the television.  The set-top box market is already crowded and each of the vendors has its own <a href="http://en.wikipedia.org/wiki/Content_delivery_network" target="_blank">content delivery network</a> (CDN), which means they are poised to compete with Netflix, even though most currently enable access to Netflix via their set-top boxes and networks.  Furthermore, the content-producing dinosaurs, who want to keep their choke hold on content distribution, <a href="http://nyti.ms/eqakwA" target="_blank">aren&#8217;t going down without a fight</a>.  They have a lot at stake.  There are undoubtedly legions of us who can&#8217;t wait to stop paying $100+ per month for a cable package just to get the small percentage of content we actually watch. To stay on top of the industry, Netflix must continue to innovate and be aggressive about making the Netflix brand synonymous with online content delivery.</p>
<p>The music industry lost its grip on the distribution chain when Napster and other peer-to-peer services set consumer&#8217;s expectations beyond the traditional model of buying CDs at brick and mortar stores.  Consumers were always willing to pay for the music they wanted, but they began to expect to be able to listen to that music on any device at any time, and they were no longer willing to be forced into a pricing model that was unfairly biased in favor of the music industry because of their control over the distribution mechanism.  In the end, the music industry was not able to hold back the tide of a la carte digital content delivery because consumers demonstrated that they were willing to steal the music en masse rather than acquiesce to the music industry&#8217;s demand to maintain the status quo (try as they did to maintain it).  The same outcome is inevitable for digital video distribution.  It&#8217;s here to stay and the content producers will ultimately have to get fully on board with an online distribution model.</p>
<p>Netflix, and <a href="http://www.akamai.com/" target="_blank">Akamai</a>, their content delivery network provider, have made some significant technical achievements to provide a quality experience for their subscribers.  They&#8217;ve built a vast network capable of staging content close to consumers  and can dynamically adjust playback quality based on available bandwidth.  Neflix has also recently jumped into <a href="http://en.wikipedia.org/wiki/Cloud_computing" target="_blank">cloud computing</a> with <a href="http://www.slideshare.net/adrianco/netflix-on-cloud-combined-slides-for-dev-and-ops" target="_blank">both feet</a>, which Computer Scientists and IT managers find interesting, but it is not really a discriminator in terms of user experience.  I don&#8217;t want to diminish any of Netflix&#8217; technical advances, but it does not appear that it would be difficult for set-top box vendors, with their own CDNs, to replicate Netflix&#8217; business model.  Apple has already demonstrated an ability to do just that with its music and movie delivery through the <a href="http://www.apple.com/itunes/" target="_blank">iTunes</a> store.  So, here are a five suggested improvements where I believe Netflix has an opportunity to step up its game.</p>
<p><strong>1) Add Linux Support</strong></p>
<p>Netflix should support video streaming for Linux platforms (feel free to sign the <a href="http://www.petitiononline.com/Linflix/" target="_blank">petition</a>).  The lack of Linux support has to do with the <a href="http://www.microsoft.com/playready/default.mspx" target="_blank">Microsoft DRM technology</a> Netflix uses to protect their movie content from unauthorized use.  You can read all about it <a href="http://jacksonh.tumblr.com/post/965806498/how-to-watch-netflix-streaming-movies-on-linux-with" target="_blank">here</a>.  Clearly Netflix has chosen to address the most widely-used platforms (Windows and Mac), but I believe that disregarding Linux support will prove to be a strategic mistake.  True, it is unlikely that the loss of revenue from Linux users is noticeable on Netflix&#8217; bottom line, but it does damage their brand.  Linux users tend to be technophiles, and if they&#8217;re shut out of Neflix&#8217; service, they&#8217;ll gravitate to an alternative that does support Linux, and where the technophiles go, the masses will follow.  The trickle of Linux users moving to an alternative service could lead to a flood of departures from Netflix, so I believe it is in their best interest to provide a Linux video streaming solution in the very near future.</p>
<p><strong>2) Downloadable Movie Rental</strong>s</p>
<p>One of the reason&#8217;s I own an <a href="http://www.apple.com/ipad/" target="_blank">iPad</a> is so that I can take media content with me when I travel.  Obviously airplanes are completely without Internet connectivity, and even though airports and hotels usually provide WiFi access points, the bandwidth is often so limited as to be nearly useless for accessing streaming media content, which means that Netflix is of no value to the traveler who wants to watch movies to help the time pass.  Conversely, <a href="http://www.apple.com" target="_blank">Apple</a>&#8216;s <a href="http://www.apple.com/itunes/" target="_blank">iTunes</a> store supports a downloadable rental feature that allows consumers to watch movies offline within 30 days of downloading the movie or to finish watching within 24 hours of first beginning the playback.  Netflix shouldn&#8217;t leave this discriminating feature to Apple and give an important segment of the user community a reason to build loyalty to a competitor.  Netflix should add the capability to download content to the local device for offline viewing (and they should probably start selling digital movies, just like Apple).</p>
<p><strong>3) Improve Search Features</strong></p>
<p><a href="http://www.hulu.com" target="_blank">Hulu</a>&#8216;s search/browse experience is richer and more accessible than what Netflix provides.  With Hulu, subscribers can use a gallery view to filter movies by key words, two levels of genre, studio and production date, in addition to a few other less-interesting filters. Conversely, Netflix subscribers can only filter a gallery view by two levels of movie genre.  After some unintuitive site navigation, users can get to a sortable list (no gallery view) that supports additional filters by year, maturity and rating.  Access to the &#8220;sortable list&#8221; feature doesn&#8217;t appear until you&#8217;ve clicked through a couple of levels of pages, which means that many will not find it at all.  However, even with the sortable list, there is still no way to filter key word searches on the Netflix site.  Shouldn&#8217;t subscribers at least be able to constrain key word searches by movie genre?  I get that most people just want the simplest possible search feature, but there should at least be an advanced feature supporting multiple constraint options.  Netflix could learn a lot from <a href="http://www.imdb.com/" target="_blank">IMDB</a>&#8216;s <a href="http://www.imdb.com/search/" target="_blank">advanced search</a> feature.</p>
<p><strong>4) Make The Netflix Site A Portal For Movie Aficionados</strong></p>
<p>I sometimes have the impression that there aren&#8217;t many true movie fanatics working at Netflix.  By making the Netflix site a portal for movie fans, Netflix can draw in potential new subscribers.  Some might argue that Netflix shouldn&#8217;t try to replicate what <a href="http://www.imdb.com" target="_blank">IMDB</a> already does well, but I disagree.  Movie fans are a lot like music fans, who obsess over every compositional element of a song or the poetry of lyrics.  They want to explore all of the technical aspects of a musical composition and know the story behind the music and the recording artist.  Movie fans are the same, and today, IMDB is their source of information for all things movie related &#8212; for past, present and future films. Netflix should replicate the IMDB model of maintaining the current pulse of the entertainment industry (movies and TV) and provide a comprehensive database of all movies, the people associated with them (cast, crew, production team), production details, technical details and extensive biographies and linkage associations between people, movies and events (e.g. premiers, awards ceremonies, etc).  By drawing in hardcore movie fans, others will follow, which will increase the prominence of the Netflix site in both the movie industry and the fan base, ultimately resulting in more subscribers for Netflix.</p>
<p><strong>5) Build A Social Network Around Netflix Subscribers</strong></p>
<p>I find it remarkable that Netflix is not integrated with social networking sites like <a href="http://www.facebook.com" target="_blank">Facebook</a> and <a href="http://www.twitter.com" target="_blank">Twitter</a>.  It appears that Netflix <a href="http://netflix.mediaroom.com/index.php?s=43&amp;item=309" target="_blank">started down this path</a> with Facebook integration in early 2009, but seems to have abandoned the effort.  The link has disappeared from Netflix&#8217; main page, although the &#8220;<a href="http://www.netflix.com/FacebookConnect" target="_blank">Facebook Connect</a>&#8221; page is still accessible with a direct link.  However, once enabled, Facebook integration appears to be broken, as no Netflix data shows up on the Facebook wall.  Virtually every news website in the world lets readers share articles they find interesting via Facebook and Twitter.  Amazon lets shoppers share products via Facebook and Twitter.  Yet, when I rate a movie or write a review on the Netflix site, there is no way for me to easily share that information to my Facebook and Twitter accounts.  Netflix is losing a huge marketing opportunity with this omission.  It is well understood that our social networks tend to be comprised of like-minded people, so when a friend recommends a movie, it is many times more influential than the recommendation of a professional movie critic.  Aside from marketing movies, allowing Netflix subscribers to post information about the movies they&#8217;ve seen to Facebook and Twitter would help to grow the Netflix brand.  When a subscriber posts a movie rating to a social networking site, they&#8217;re not just endorsing a movie, they&#8217;re also endorsing the Netflix service.  I can only assume that Netflix is already way ahead of me on this, and a team is about to roll out their new and improved social networking integration any day now.</p>
<p>In addition to integrating with existing social networking sites, Netflix should build their own social network around their content, including the enhancements described in recommendation #4.  To be fair, Netflix <a href="http://www.blogherald.com/2010/09/05/netflix-pulls-the-plug-on-social-network/" target="_blank">already tried this</a> but ultimately shuttered the site&#8217;s &#8220;Community&#8221; features to devote engineering resources elsewhere.  It also seems that Netflix&#8217;s social networking features may not have provided sufficient privacy controls to allow users to filter what they share about their viewing habits, which could have made Netflix&#8217; social networking features unpopular.  Facebook has been slow to address the same need for granular privacy features &#8212; we don&#8217;t necessarily want to share the same things with our mom and our drinking buddies &#8212; but that doesn&#8217;t mean social networking should be abandoned.  Yes, first and foremost Netflix must flawlessly deliver content, but their competitors can do that too.  Netflix needs discriminators, and building a social network around their service could be a big one.  Today, the Netflix site is very basic.  You can search for a movie, add it to a queue and either receive it through the mail or stream it instantly.  Social networking could make the Netflix site much more engaging, which would bring in new subscribers and put them in touch with more movies they want to watch.</p>
<p>At a minimum, the Netflix site should allow subscribers to create a personal profile that can be shared with others.  Profiles could enable users to create and share lists of movies around genres, topics, studios, actors and directors, to subscribe to profiles for studios, actors and directors, to receive change notifications, to aggregate movie reviews and to moderate discussion forums, just to name a few potential features.  The best way to find movies we like is to find people like ourselves who like movies.  The Netflix site does support a simple subscriber profile today, which appears to serve the exclusive purpose of associating movie reviews to a subscriber, but there is no networking capability.  A crude, unaffiliated &#8220;Netflix Community&#8221; <a href="http://netflixcommunity.ning.com/" target="_blank">site</a> has emerged to fill the space that Netflix is leaving unoccupied.</p>
<p><a href="http://www.apple.com" target="_blank">Apple</a>&#8216;s <a href="http://www.apple.com/itunes/ping/" target="_blank">Ping</a> social network for music is an example that Netflix could follow.  Apple understands the value of the social network &#8212; consumers buy what their friends buy &#8212; so they&#8217;ve developed Ping, which is integrated with the <a href="http://www.apple.com/itunes/" target="_blank">iTunes</a> music store.  Netflix should also learn from what Apple has done wrong with Ping.  Households typically have one account for online storefronts, with multiple members of the household buying products through the single account.  With iTunes and Ping, this causes a confusing social networking experience.  Adults probably don&#8217;t want their children&#8217;s music purchases associated with their social network profile, and the same would be true for movie preferences.  This also tends to be a problem with recommendation systems.  If you&#8217;re sharing an account, the recommendations become polluted because each different user&#8217;s orthogonal preferences are combined into a single profile.  Netflix has an opportunity to do something new and discriminating by combining online media distribution, retail and social networking into a high quality user experience.</p>
<p><strong>Conclusion</strong></p>
<p>Each of these recommendations is meant to address improvements that will add discriminators to the Netflix service in an increasingly competitive market.  It goes without saying that offering current content that consumers want to watch is the single biggest discriminator for Netflix, but that is largely a business consideration to be negotiated with content producers and outside the scope of an engineer&#8217;s purview.  Netflix already offers a great service and is the clear leader in the industry, but if they are to continue to dominate, Netflix must continue to innovate in ways that enrich the subscriber experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/5-ways-to-improve-netflix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Started with Amazon&#8217;s Elastic Compute Cloud</title>
		<link>http://engineeringnotebook.org/getting-started-with-ec2/</link>
		<comments>http://engineeringnotebook.org/getting-started-with-ec2/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 02:57:00 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[SaaS]]></category>
		<category><![CDATA[Software Architecture]]></category>
		<category><![CDATA[Web Services]]></category>
<category>amazon ec2</category><category>ami</category><category>aws</category><category>cloud computing</category><category>ec2</category><category>SaaS</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1747</guid>
		<description><![CDATA[I&#8217;ve recently started working with Amazon&#8217;s Elastic Compute Cloud (EC2) for my personal project and decided to capture the answers to some of the beginner questions that I worked through. Amazon provides a great deal of documentation, but I believe the organization of their documentation could use some work.  Before you begin working with EC2, you should start by reading Amazon&#8217;s Getting Started Guide.  Here are the answers to some basic start-up questions: 1) How do I launch an instance of an [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently started working with <a href="http://aws.amazon.com/ec2/" target="_blank">Amazon&#8217;s Elastic Compute Cloud</a> (EC2) for my <a href="http://engineeringnotebook.org/project-overview/" target="_blank">personal project</a> and decided to capture the answers to some of the beginner questions that I worked through. Amazon provides a great deal of documentation, but I believe the organization of their documentation could use some work.  Before you begin working with EC2, you should start by reading Amazon&#8217;s <a href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/" target="_blank">Getting Started Guide</a>.  Here are the answers to some basic start-up questions:</p>
<p><strong>1) How do I launch an instance of an Amazon Machine Image (AMI)?</strong></p>
<p>You can find the answer <a href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/index.html?LaunchInstance.html" target="_blank">here</a>.  Launching an instance of an AMI gives you a running &#8220;machine&#8221; that conforms to the configuration of the specific AMI, on which you can then deploy your applications.  You can find a list of available AMIs <a href="http://aws.amazon.com/amis" target="_blank">here</a>.</p>
<p><strong>2) How do I connect to my machine instance?</strong></p>
<p>You&#8217;ve started your instance, now you want to open a terminal session to it from your local workstation.  You&#8217;ll need to use <a href="http://en.wikipedia.org/wiki/Secure_Shell" target="_blank">SSH</a> with the key file you generated when you launched your instance.  You can find a detailed explanation <a href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/index.html?ConnectToInstanceLinux.html" target="_blank">here</a>.  The SSH command will look like this:</p>
<p style="font-family: 'Courier New', Courier, mono;">ssh -i keyfile.pem username@hostname</p>
<p>The root user login has been disable, so instead each image has a default username that you must use to SSH in to the instance.  I have found that the default user name sometimes pops up in a dialogue box when you launch the instance, but more often than not it doesn&#8217;t and you have to hunt for it.  For example, the user name for Amazon&#8217;s Linux image can be found in their <a href="http://ec2-downloads.s3.amazonaws.com/AmazonLinuxAMIUserGuide.pdf" target="_blank">user guide</a>.  Alternatively, if you just try to SSH into your instance using &#8220;root&#8221; for the username, the connection will fail and respond with the required username.  It&#8217;s the fastest way I&#8217;ve found to find the right username, but if someone knows where I can find it in the <a href="http://aws.amazon.com/console/" target="_blank">AWS management console</a>, please let me know.</p>
<p><strong>3) How do I load my own software on the instance I started?</strong></p>
<p>Amazon&#8217;s documentation isn&#8217;t very clear on this.  You&#8217;ll need to use <a href="http://en.wikipedia.org/wiki/Secure_copy" target="_blank">SCP</a> to upload files from your local machine to your running instance.  The command to upload a source file on your local machine to a target file on your running instance will look like this:</p>
<p style="font-family: 'Courier New', Courier, mono;">scp -i keyfile.pem source-file-name username@hostname:target-file-name</p>
<p>You&#8217;ll use the key file that you generated when you launched your instance (the same one you used for your SSH session).  The default username is the same one you used to establish an SSH session, described above.  The host name (public DNS) is available in the <a href="http://aws.amazon.com/console/">AWS management console</a>, described in the metadata for your running instance.</p>
<p><strong>4) Once I&#8217;ve gotten my AMI configured the way I want it, how do I save it for future use?</strong></p>
<p>Amazon&#8217;s documentation is somewhat lacking on this subject.  It can be a little difficult to decipher the <a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?Concepts_BootFromEBS.html" target="_blank">difference</a> between an S3-backed instance and an<a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?Concepts_BootFromEBS.html" target="_blank">EBS-backed instance</a> or to understand the use cases that would motivate you to choose one over the other.  According to Amazon&#8217;s <a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?Concepts_BootFromEBS.html" target="_blank">documentation</a>:</p>
<blockquote><p>An Amazon EC2 instance can be launched from an AMI backed by Amazon EBS or from an AMI backed by Amazon S3. Instances launched from AMIs backed by Amazon EBS use Amazon EBS volumes as their root devices. Instances launched from AMIs backed by Amazon S3 use an instance store as the root device (e.g., / or C:\).</p></blockquote>
<p>There&#8217;s a bit of ambiguity here.  What does it mean to say that an S3-backed instance has an instance store as the root device?  After reading <a href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?Concepts_BootFromEBS.html" target="_blank">more</a> documentation, what I think this means is that the state of the S3-backed images is strictly transient.  Once you terminate the instance, any changes you make to the instance configuration are lost.  For S3-backed instances, the root device persistence is on the local disk (instance store) of the machine on which the instance is running, which is only available for the life of the instance.  Conversely, when you stop an EBS-backed instance, its state is automatically persisted to an EBS volume.  Stopping an instance is not the same as terminating an instance.  A terminated instance cannot be restarted.  So, if you want to make changes to your instance configuration and keep it around for future use, you must create an EBS-backed instance, and you should only stop it, don&#8217;t terminate it.</p>
<p>Having said all of that, what you really want to do is to create a new AMI based on the running instanced you&#8217;ve configured.  Although there is a browser-based management console that will let you start instances of existing AMIs, it looks like one must use the <a href="http://aws.amazon.com/developertools/351?_encoding=UTF8&amp;jiveRedirect=1" target="_blank">command line API tools</a> to save your configured instance..  Once you&#8217;ve created the new AMI, you can then instantiate it from the console at a future time.  The command to create the image from the instance follows below.</p>
<p><code style="font-family: 'Courier New', Courier, mono;">ec2-create-image <code>instance_id</code> [--name <code>name</code>, --description <code>description</code>, --no-reboot]</code></p>
<p>The instance_id can be retrieved from the web console for the running instance that you want to save as your new AMI.  The documentation for all of the command line tools can be found <a href="http://docs.amazonwebservices.com/AWSEC2/latest/CommandLineReference/" target="_blank">here</a>.  It takes a little bit of effort to get your local environment set up to run the command line tools, but the documentation is clear and straightforward, so there&#8217;s no point in repeating it here.</p>
<p>I&#8217;ve only covered the basics in this post, which I&#8217;m turning into a <a href="http://engineeringnotebook.org/amazon-ec2-howto/" target="_blank">HowTo</a> that I&#8217;ll continue to evolve as I work through more complex use cases.  The next step for me is to push some of my existing code into the EC2 and investigate how I&#8217;ll use Amazon&#8217;s cloud features (databases, messaging, etc) so that I can nail down what my target architecture will look like.  I&#8217;m also still looking into what my development model will look like &#8211; i.e. how much code I can write and test in my local environment versus what I need to move into the cloud, since Amazon does not provide an emulation environment for developers.  More to come.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/getting-started-with-ec2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Architecting for the Cloud</title>
		<link>http://engineeringnotebook.org/architecting-for-the-cloud/</link>
		<comments>http://engineeringnotebook.org/architecting-for-the-cloud/#comments</comments>
		<pubDate>Mon, 06 Dec 2010 05:26:58 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Software Architecture]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Web Services]]></category>
<category>amazon ec2</category><category>cloud computing</category><category>jee</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1622</guid>
		<description><![CDATA[My intention is for most, if not all, of the software I write for this project to run on the server side.  I plan to expose a RESTful Web Service API to consumers, which will authorize my software to retrieve their data from social networking sites and in return provide highly tailored recommendations for movies, books, businesses, etc, and connections to other social networking users.  I&#8217;ve outlined the project&#8217;s objectives here.  I&#8217;m now examining potential server side architectures and prototyping [...]]]></description>
			<content:encoded><![CDATA[<p>My intention is for most, if not all, of the software I write for <a href="http://engineeringnotebook.org/project-overview/" target="_blank">this project</a> to run on the server side.  I plan to expose a <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer" target="_blank">RESTful Web Service</a> API to consumers, which will authorize my software to retrieve their data from social networking sites and in return provide highly tailored recommendations for movies, books, businesses, etc, and connections to other social networking users.  I&#8217;ve outlined the project&#8217;s objectives <a href="http://engineeringnotebook.org/project-overview/" target="_blank">here</a>.  I&#8217;m now examining potential server side architectures and prototyping a few options.  The first option I&#8217;ve considered is to use <a href="http://www.oracle.com/technetwork/java/javaee/overview/index.html" target="_blank">Java enterprise</a> technologies and deploy software in the <a href="http://glassfish.java.net/" target="_blank">Glassfish</a> Application Server.  Why Java EE?  Because it provides the kind of capabilities that one would want in a reliable, scalable, manageable server side architecture and has support for the necessary transports baked into the API, such as Web Services, JMS and XML and JSON marshaling.  Why Glassfish?  The primary reason for selecting Glassfish is that I use it at my day job, and we&#8217;ve had good luck using it on a large, enterprise software project, so I believe it&#8217;s a quality product.  I also prefer using open source products when I can.</p>
<p>Although I have a high opinion of Glassfish and the JEE suite, I find the arguments in favor of <a href="http://en.wikipedia.org/wiki/Cloud_computing">cloud computing</a> increasingly persuasive.  For me, a rather simple and compelling argument has to do with the accessibility of large-scale hardware.  This is a personal project, so I&#8217;m using personal resources.  In terms of hardware, that means using my <a href="http://www.apple.com/macbook/" target="_blank">MacBook</a> and my PC server running <a href="http://www.ubuntu.com/" target="_blank">Ubuntu</a>.  I don&#8217;t want to go out and buy a scalable hardware configuration to use in my personal development environment, which  will inevitably be different from the deployment environment that I&#8217;d pay for at some Web hosting company&#8217;s data center.  We run into this dilemma at my day job all the time.  Our production deployment environment is an expensive N+1 configuration involving many high-end servers to support load balancing and clustering of JEE App Servers, Oracle DBs, JMS message brokers, etc.  We attempt to create representative hardware configurations in our distributed development centers and in multiple testing facilities.  This has turned out to be costly, and it has been difficult to maintain configuration control over multiple environments.  With multiple, external software vendors developing pieces of the system, the cost and complexity is exacerbated.  Just the planning and labor to install, configure and maintain so many resources in our development and test facilities is a large burden.  We&#8217;re always discovering a hardware shortfall somewhere, which takes time to resolve, which delays our software deliveries.  Our teams often end up developing and testing in non-representative environments, which leads to late discovery of complex bugs related to scalability and reliability.  As the chief architect on this project, I&#8217;m often asked to define the minimal representative hardware environment.  Good luck with that one.</p>
<p>Another reason I find cloud computing valuable is that it takes the hardware problem off of my plate.  I&#8217;m a <a href="http://engineeringnotebook.org/about/" target="_blank">software guy</a>, so I really don&#8217;t give a fig about developing and managing an IT infrastructure.  Again, I&#8217;ll use my day job as an example.  Because we&#8217;re building our own data centers to host our software, I have to spend time attempting to give requirements to our hardware team well in advance of when we could definitively specify those requirements.  For example, how many servers will we need to host our software?  Well, I don&#8217;t know for sure until we have a critical mass of software to allow us to empirically create some meaningful performance profiles.  We may have to make several adjustments to the planned deployment configuration to address load balancing issues or resolve performance bottlenecks, yet our hardware team needs to procure hardware months in advance of our software deliveries to create testing environments and to install data centers at remote locations.  This will cause me endless pain when I have to ask the hardware team to change the production deployment configuration after installation.  <a href="http://perfcap.blogspot.com/" target="_blank">Adrian Cockcroft</a> recently made <a href="http://www.slideshare.net/adrianco/netflix-on-cloud-combined-slides-for-dev-and-ops" target="_blank">similar points</a> when discussing <a href="http://www.netflix.com/" target="_blank">Netflix</a>&#8216; migration to <a href="http://aws.amazon.com/ec2/" target="_blank">Amazon&#8217;s cloud</a>.</p>
<p>So, I&#8217;ve decided to develop my software to run within a cloud, and I&#8217;ve settled on the Amazon cloud platform.  I don&#8217;t know if it&#8217;s the best cloud architecture and toolset, but it does seem to be the most mature and widely used.  That&#8217;s good enough for me to move on.</p>
<p>I&#8217;ve started reviewing Amazon&#8217;s <a href="http://aws.amazon.com/documentation/" target="_blank">developer documentation</a>, and after evaluating the SOAP and REST <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/" target="_blank">APIs</a>, I have initially settled on using their <a href="http://aws.amazon.com/sdkforjava/" target="_blank">Java SDK</a>.  I&#8217;m now working through some of the <a href="http://aws.amazon.com/articles/3586?_encoding=UTF8&amp;jiveRedirect=1" target="_blank">examples</a> and trying to get a better feel for the programming model.  It looks to me like traditional enterprise computing frameworks, like Java EE, are mutually exclusive with Amazon&#8217;s API.  By which I mean that Amazon seems to have built its own framework from scratch, supporting scalability (<a href="http://aws.amazon.com/ec2/" target="_blank">EC2</a>), database access (<a href="http://aws.amazon.com/simpledb/" target="_blank">SimpleDB</a>, <a href="http://aws.amazon.com/rds/" target="_blank">RDS</a>), large-scale data processing (<a href="http://aws.amazon.com/elasticmapreduce/" target="_blank">MapReduce</a>),  messaging (<a href="http://aws.amazon.com/sqs/" target="_blank">SQS</a>, <a href="http://aws.amazon.com/sns/" target="_blank">SNS</a>) and storage (<a href="http://aws.amazon.com/s3/" target="_blank">S3</a>, <a href="http://aws.amazon.com/ebs/" target="_blank">EBS</a>).  There is <a href="http://aws.amazon.com/articles/Java/1084" target="_blank">some indication</a> that Java EE applications can be deployed within the Amazon cloud, but this does not seem to be the model for developing new applications that are &#8220;native&#8221; to Amazon&#8217;s cloud platform.</p>
<p>My next step is to dive into porting my initial POJO code over to Amazon&#8217;s cloud, which means working to become familiar with their API.  I&#8217;ll provide progress updates within a few days.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/architecting-for-the-cloud/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OAuth Solution</title>
		<link>http://engineeringnotebook.org/oauth-solution/</link>
		<comments>http://engineeringnotebook.org/oauth-solution/#comments</comments>
		<pubDate>Mon, 06 Dec 2010 02:26:44 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[Web Services]]></category>
<category>oauth</category><category>scribe</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1671</guid>
		<description><![CDATA[In a previous post, I discussed the evaluation of a couple of different Java OAuth libraries.  I started with Scribe, and so far it&#8217;s working as advertised.  I was able to use it to authorize my Java client to access a protected twitter resource (from my own account), using the out of band approach, and it worked perfectly.  The Scribe code is well written (kudos to Pablo Fernandez), so my only complaint is the lack of API documentation.  It&#8217;s not much of a complaint though, [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://engineeringnotebook.org/jersey-support-for-oauth/" target="_blank">previous post</a>, I discussed the evaluation of a couple of different Java <a href="http://oauth.net/" target="_blank">OAuth</a> libraries.  I started with <a href="https://github.com/fernandezpablo85/scribe-java" target="_blank">Scribe</a>, and so far it&#8217;s working as advertised.  I was able to use it to authorize my Java client to access a protected twitter resource (from <a href="http://twitter.com/#!/JCinSanDiego" target="_blank">my own account</a>), using the out of band approach, and it worked perfectly.  The Scribe code is well written (kudos to <a href="http://www.linkedin.com/in/fernandezpablo85" target="_blank">Pablo Fernandez</a>), so my only complaint is the lack of API documentation.  It&#8217;s not much of a complaint though, since the example code provided is easy to follow.  Unless I run into some show stopper with Scribe (unlikely), that&#8217;s what I&#8217;m sticking with.  So, that ends my OAuth adventure.  I&#8217;ve now moved on to evaluating potential server-side architectures.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/oauth-solution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Social Networking Project Overview</title>
		<link>http://engineeringnotebook.org/project-overview/</link>
		<comments>http://engineeringnotebook.org/project-overview/#comments</comments>
		<pubDate>Mon, 29 Nov 2010 03:47:26 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Data Mining]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[Web Services]]></category>
<category>Data Mining</category><category>restful</category><category>Social Networking</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1630</guid>
		<description><![CDATA[I previously wrote a short description of the social networking software project that I recently started.  I&#8217;ve tried to capture the highlights in the two Activity diagrams below.  The first diagram illustrates the workflow for mining patterns from a user&#8217;s social networking data after being combined with the patterns from other uses into a global model.  The second diagram illustrates the workflow for applying the mined patterns to construct user-specific queries for services like Netflix, Amazon and Yelp, all of [...]]]></description>
			<content:encoded><![CDATA[<p>I previously <a href="http://engineeringnotebook.org/new-social-networking-project/" target="_blank">wrote</a> a short description of the social networking software project that I recently started.  I&#8217;ve tried to capture the highlights in the two <a href="http://en.wikipedia.org/wiki/Activity_diagram" target="_blank">Activity diagrams</a> below.  The first diagram illustrates the workflow for mining patterns from a user&#8217;s social networking data after being combined with the patterns from other uses into a global model.  The second diagram illustrates the workflow for applying the mined patterns to construct user-specific queries for services like <a href="http://www.netflix.com" target="_blank">Netflix</a>, <a href="http://www.amazon.com" target="_blank">Amazon</a> and <a href="http://www.yelp.com" target="_blank">Yelp</a>, all of which provide developer APIs.  Most of my effort to date has been on the mechanics of retrieving data from the social networking services (i.e. <a href="http://www.twitter.com" target="_blank">Twitter</a> and <a href="http://www.facebook.com" target="_blank">Facebook</a>).  The real crux of the project is to provide a value-added recommendation service that is built upon relational data mining techniques, which was the subject of my <a href="http://scholar.google.com/scholar?hl=en&amp;q=graph+data+mining+coble&amp;btnG=Search&amp;as_sdt=2000&amp;as_ylo=&amp;as_vis=1" target="_blank">previous research work</a>.  More to come&#8230;</p>
<p style="text-align: center;"><a href="http://engineeringnotebook.org/wp-content/uploads/2010/11/Slide2.jpg"><img class="aligncenter" src="http://engineeringnotebook.org/wp-content/uploads/2010/11/Slide2.jpg" alt="Project Activity Diagrams" width="518" height="389" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/project-overview/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Jersey Support for OAUTH</title>
		<link>http://engineeringnotebook.org/jersey-support-for-oauth/</link>
		<comments>http://engineeringnotebook.org/jersey-support-for-oauth/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 02:23:30 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[Web Services]]></category>
<category>jersey</category><category>maven</category><category>oauth</category><category>restful</category><category>Social Networking</category><category>Twitter</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1611</guid>
		<description><![CDATA[As I reported in my last post, I have been working to add OAUTH support into my Twitter client.  According to Sun&#8217;s wiki, the Jersey client API is supposed to have classes supporting OAUTH interactions.  Unfortunately, in the latest API documentation, those OAUTH classes are gone.  It looks like I&#8217;ll have to look elsewhere for a client-side Java OAUTH library.  The best candidates seem to be Google&#8217;s OAUTH Library and Scribe.  The latter seems to be well tested against major web [...]]]></description>
			<content:encoded><![CDATA[<p>As I reported in my <a href="http://engineeringnotebook.org/initial-twitter-client/" target="_blank">last post</a>, I have been working to add <a href="http://oauth.net/" target="_blank">OAUTH</a> support into my <a href="http://twitter.com" target="_blank">Twitter</a> client.  According to Sun&#8217;s <a href="http://wikis.sun.com/display/Jersey/OAuth">wiki</a>, the <a href="http://jersey.java.net/" target="_blank">Jersey</a> client API is supposed to have classes supporting OAUTH interactions.  Unfortunately, in the latest <a href="http://jersey.java.net/nonav/apidocs/latest/jersey/index.html" target="_blank">API documentation</a>, those OAUTH classes are gone.  It looks like I&#8217;ll have to look elsewhere for a client-side Java OAUTH library.  The best candidates seem to be Google&#8217;s <a href="http://oauth.googlecode.com/svn/code/java/" target="_blank">OAUTH Library</a> and <a href="https://github.com/fernandezpablo85/scribe-java" target="_blank">Scribe</a>.  The latter seems to be well tested against major web services, so I&#8217;ll probably start there.  It&#8217;s unclear whether I&#8217;ll still be able to use the Jersey client API at all.  I&#8217;m not sure if the OAUTH API library will be compatible with the Jersey Client API.  I&#8217;m fairly annoyed with Jersey anyway.  I spent way too much time trying to figure out what happened to their OAUTH support.  Maybe it&#8217;s not ready for prime time, at least on the client side.</p>
<p>On a side note, I have finally taken the plunge and started working with <a href="http://maven.apache.org/" target="_blank">Maven</a>.  I had resisted it in the past, preferring to keep my development environment simple and under my control.  However, it&#8217;s gotten to the point where it&#8217;s difficult to avoid using Maven because so many other projects use it (our development team uses it at my work).  There&#8217;s almost an expectation now that one is adding in 3rd party dependencies via Maven.  So, I&#8217;ve spent a little time this week <a href="http://www.amazon.com/Maven-Definitive-Guide-Sonatype-Company/dp/0596517335/ref=sr_1_1?ie=UTF8&amp;qid=1289787489&amp;sr=8-1" target="_blank">reading</a> up on Maven and the glory of <a href="http://maven.apache.org/pom.html" target="_blank">POM</a> files.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/jersey-support-for-oauth/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Initial Twitter Client</title>
		<link>http://engineeringnotebook.org/initial-twitter-client/</link>
		<comments>http://engineeringnotebook.org/initial-twitter-client/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 02:13:28 +0000</pubDate>
		<dc:creator>Jeff Coble</dc:creator>
				<category><![CDATA[Data Mining]]></category>
		<category><![CDATA[Social Networking]]></category>
		<category><![CDATA[Web Services]]></category>
<category>Data Mining</category><category>oauth</category><category>restful</category><category>Social Networking</category><category>Twitter</category><category>web services</category>
		<guid isPermaLink="false">http://engineeringnotebook.org/?p=1589</guid>
		<description><![CDATA[I&#8217;ve been down with a cold for about a week, so my apologies for the delayed update.  I finished coding a simple Twitter client to retrieve a list of friend&#8217;s statuses for a user, using Twitter&#8217;s RESTful web services API.  I wrote previously about the absence of XML schemas to define the twitter response formats.  As I&#8217;ve done more reading, it seems this is typical for RESTful web services, but I&#8217;m not entirely sure the arguments about decoupling are really [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been down with a cold for about a week, so my apologies for the delayed update.  I finished coding a simple <a href="http://twitter.com" target="_blank">Twitter</a> client to retrieve a list of friend&#8217;s statuses for a user, using <a href="http://dev.twitter.com/doc" target="_blank">Twitter&#8217;s RESTful web services API</a>.  I wrote <a href="http://engineeringnotebook.org/writing-a-restful-web-service-client/" target="_blank">previously</a> about the absence of XML schemas to define the twitter response formats.  As I&#8217;ve done more reading, it seems this is typical for RESTful web services, but I&#8217;m not entirely sure the arguments about decoupling are really solid.  More on that in the future.  Although I was able to use <a href="http://www.thaiopensource.com/relaxng/trang.html" target="_blank">Trang</a> to generate the schema for the friend status list XML response<a href="http://www.thaiopensource.com/relaxng/trang.html" target="_blank"></a>, I decided not to go with a direct schema binding solution for my client because first, I thought the generated schema was overly generic (no surprise) and would require some manual manipulation before I would want to run it through a <a href="http://www.oracle.com/technetwork/articles/javase/index-140168.html" target="_blank">JAXB</a> binding compiler, and second, I was concerned that the resultant JAXB binding would be very brittle if the folks at Twitter decided to change their XML structure in minor ways. I decided to use a <a href="http://download.oracle.com/javase/6/docs/api/javax/xml/parsers/SAXParser.html" target="_blank">SAX parser</a> instead because I thought it would be more resilient to minor structural changes to the XML than JAXB.  I&#8217;ve never actually used JAXB for anything, so this may not have been a good assumption on my part.  I do plan to get more familiar with JAXB soon, since it seems to be what most JAVA developers are now using for XML manipulation.</p>
<p>So, I have coded all of this up, including the beginnings of a simple object model for user data, and have been able to pull in the friend status data from Twitter and verify that my object model is being instatiated and populated correctly.  The next step is to get <a href="http://oauth.net/" target="_blank">OAUTH</a> working correctly as a precursor to deploying this client as a service, where a user could delegate authorization to my service to retrieve account data for the purposes of creating a pattern matching profile.  Although it looks to be a little dated, this <a href="http://hueniverse.com/2007/10/beginners-guide-to-oauth-part-i-overview/" target="_blank">OAUTH tutorial</a> has been useful.  More on OAUTH in my next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://engineeringnotebook.org/initial-twitter-client/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

