<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3413472902245248871</atom:id><lastBuildDate>Fri, 25 Oct 2024 05:03:53 +0000</lastBuildDate><title>The time poor programmer</title><description>Fed up with falling into code holes you never knew were there?&#xa;&#xa;We don&#39;t claim to know it all, we just hope to explain technology that vexed us, well enough to get you going too.&#xa;&#xa;May the time poor programmer be with you.</description><link>http://timepoorprogrammer.blogspot.com/</link><managingEditor>noreply@blogger.com (Jim B)</managingEditor><generator>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-7704366945570278149</guid><pubDate>Thu, 04 Apr 2013 22:14:00 +0000</pubDate><atom:updated>2013-04-04T23:43:44.198+01:00</atom:updated><title>Continuous Delivery : Part 1: What is it?</title><description>So this is the first in a series of continuous delivery blog posts that we hope you can use for inspiration and guidance or toilet-paper whatever your need.&lt;br /&gt;
Through the series, we’ll go the whole way, from describing what continuous delivery is, through what tools to use and why, to creating your development environment, and all the way to automating your delivery and collating metrics.&amp;nbsp; &lt;br /&gt;
Any examples will be by reference to a&amp;nbsp; scale-able REST JSON public service API and the problems and issues we’ve had to solve along the way.&lt;br /&gt;
&lt;h2&gt;&lt;/h2&gt;&lt;h2&gt;&lt;/h2&gt;&lt;h2&gt;PICTURES PLEASE&lt;/h2&gt;You might be using continuous integration in your workplace or at home, and it may be something you are familiar with. &lt;br /&gt;
Chances are CI works really well within your team, and on your project, but doesn’t work so well across all projects, and probably sucks between departments, particularly as your development moves towards being released in front of customers.&lt;br /&gt;
Software development paradoxically is an industry where the standard production line to deployment becomes progressively more manual the closer you get to the customers. &lt;br /&gt;
This is such a waste of time and money. &lt;br /&gt;
There are some great books on the topic of CI and its bigger and bolder brother Continuous Delivery which attempts to address the problem above.&amp;nbsp; Here we’ll pick out Jez Humble and David Farley’s epic &lt;a href=&quot;http://www.amazon.com/dp/0321601912?tag=contindelive-20&quot;&gt;Continuous Delivery&lt;/a&gt; for background reading, but as with most things, you haven’t got time, its a big topic, so we’ve tried to explain it in pictures.&lt;br /&gt;
&lt;h2&gt;&lt;/h2&gt;&lt;h2&gt;development RELEASE phase&lt;/h2&gt;Here is a picture for an idealised development release phase for a complicated project with lots of technologies.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZbooSyUdfn9Zp-yBG0GRkDEgJH7fkM8s5LkhXaKyalOfAnd6IFYQutdTeMIuJIA1fBAmB5x-6Z35wQWFirBM7GfjrvlQz7x7C18xw37fmPQSEWlz0ILivIUlpDdQmMJWsFihROPGLUGmO/s1600/build_architecture_development_release.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZbooSyUdfn9Zp-yBG0GRkDEgJH7fkM8s5LkhXaKyalOfAnd6IFYQutdTeMIuJIA1fBAmB5x-6Z35wQWFirBM7GfjrvlQz7x7C18xw37fmPQSEWlz0ILivIUlpDdQmMJWsFihROPGLUGmO/s320/build_architecture_development_release.png&quot;/&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
On a complicated project, there may be many different parts to the overall project.&amp;nbsp; The process may differ from team to team and technology to technology, but a few key pieces can be observed in any process and for any technology that need to be common:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;All pieces of a complicated project should be under version control, hence the &lt;i&gt;team version control repository&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Each piece of the complicated project should&amp;nbsp; be built centrally on the team’s &lt;i&gt;continuous build server &lt;/i&gt;so all changes get batched up and built as part of the normal process of continuous build or continuous integration (see &lt;a href=&quot;http://martinfowler.com/articles/continuousIntegration.html&quot;&gt;Continuous Integration&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Once successfully built, the artifact (JAR, EXE, ZIP, GEM, RPM, whatever) that is the product of a build should be deployed to an artifact repository that is visible to &lt;i&gt;all &lt;/i&gt;teams under a known set of GAV co-ordinates (Group, Artifact, Version) so that something further downstream (closer to being in front of a customer) can depend on (so download) the built artifact as part of a larger whole.&lt;/li&gt;
&lt;/ol&gt;So.&amp;nbsp; We’ve got lots of teams building different parts of a solution at known versions to an artifact repository, but what about the solution as a whole, as none of the individual bits of solution can be released to being in-front of a customer, only the whole can? &lt;br /&gt;
This is where the second picture comes in.&lt;br /&gt;
&lt;h2&gt;Product release phase&lt;/h2&gt;Any moderately complicated solution is going to be made up of many different parts, software, hardware, configuration, and supporting 3rd party applications.&lt;br /&gt;
What often happens if you work in a place where there is a separation between development and any other part of the business (&lt;i&gt;&lt;b&gt;a.k.a&lt;/b&gt; the usual hell&lt;/i&gt;), is your artifact that is only a small part of the overall solution falls off the end of the development conveyor belt, crashes to the floor, and is at some indeterminate point in the future is swept up and taken on by people who may have never seen it before, and have no idea what to do with it. &lt;br /&gt;
Sound familiar?&lt;br /&gt;
The result of this lack of departmental collectivism is as a general rule, chaos, panic, bad blood, all of the above, particularly as &lt;i&gt;product release &lt;/i&gt;time nears.&lt;br /&gt;
So things need to be joined up don’t they?&lt;br /&gt;
Here is a picture of what could happen after the development release phase of each component part of a solution or product:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6n6oAjFUYD9RU9ykTiKF1kjAwwU-AwzMbJ1vJyNDaI1IBrV2d0LS3eEZARyrAHg9tT9lDb3vJEmxgcXKzMBCiRe1G3l3DKY-tTTZUEcPAnneB-ETC8hKgzT34bgChLQA376LbTDqf0FbO/s1600/build_architecture_product_release.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6n6oAjFUYD9RU9ykTiKF1kjAwwU-AwzMbJ1vJyNDaI1IBrV2d0LS3eEZARyrAHg9tT9lDb3vJEmxgcXKzMBCiRe1G3l3DKY-tTTZUEcPAnneB-ETC8hKgzT34bgChLQA376LbTDqf0FbO/s320/build_architecture_product_release.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The solution or product is made of constituent parts at known versions.&amp;nbsp; This bundle of parts can each be pulled from the DEV artifact repository, and can be expressed as a file with a known version of its own (a Maven POM anyone?) so long as that file is accessible to external systems by GAV co-ordinates too.&lt;br /&gt;
This bundle moves through certain stages towards delivery.&amp;nbsp; These are the stages in a &lt;i&gt;deployment&lt;/i&gt; &lt;i&gt;pipeline, &lt;/i&gt;such as automated acceptance testing, automated performance testing, durability testing, whatever stages you (as you are in control aren’t you?) want to include in your pipeline. &lt;br /&gt;
Note a few observations can be made here:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;If DEV don’t become more OPS, then you are in trouble.&lt;/li&gt;
&lt;li&gt;If OPS don’t become more DEV, then you are in trouble.&lt;/li&gt;
&lt;li&gt;The &lt;i&gt;Product Artifact Repository &lt;/i&gt;needn’t be the same as the &lt;i&gt;DEV Artifact Repository&lt;/i&gt;.&amp;nbsp; The &lt;i&gt;Product Artifact Repository&lt;/i&gt; refers to bundles (expressed as products) that move down a pipeline, so if we need to get pointy-headed about security, we can do it here if we so wish&lt;/li&gt;
&lt;li&gt;To move through a stage in the pipeline, a bundle gets deployed, provisioned, and tested on a representative deployment environment using the tests that “fit” with that stage.&amp;nbsp; If it passes, it gets moved down the pipeline, otherwise it doesn’t.&lt;/li&gt;
&lt;li&gt;Moving down a pipeline could mean many things, logically promoting a given bundle to a new state following completion, actually copying bundles of stuff from one location to another (I don’t recommend this), doing a combination of the both.&lt;/li&gt;
&lt;li&gt;Eventually the bundle makes it to a staging environment, and its done everything but go live.&amp;nbsp; You do &lt;i&gt;canary releasing &lt;/i&gt;right, and you’ve got in-flight upgrades sorted right? No? Never mind we’ll cover those in later posts, as ideally, you would want to automate your migration from an old version of your solution to a new version of your solution, all the way to live, without your customer even noticing it.&lt;/li&gt;
&lt;li&gt;So, now we are live.&amp;nbsp; What if no-one wants the solution? What do you mean you’ve got no metrics that tell you what is used, and if its used? Are you used to burning money? A principal aim of Continuous Delivery is, do it regularly and do it in small increments. So, if the real metrics tell you no-one wants your brilliant new or planned feature, then its not a fiasco, and don’t keep it, bin it. But bin it on the basis of actual user feedback not on the basis of imagined need.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;Hopefully the pictures set the scene enough to begin the conversion within your own organisation, and set the scene for the posts to follow.&amp;nbsp;&amp;nbsp; &lt;br /&gt;
In our opinion, the biggest two obstacles to the widespread adoption of Continuous Delivery are politics, and short-termism.&lt;br /&gt;
If you aren’t doing Continuous Delivery already, you can bet your life either your competition will be, or are currently thinking of doing it soon. So get a move on before your politics and short-termism kill you as a competitive business.&lt;br /&gt;
In the following series of blog posts we’ll investigate what it all means, and how you actually do it.&lt;br /&gt;
Enjoy.&lt;br /&gt;
The next blog post will be on the basic toolkit we found we needed and why …</description><link>http://timepoorprogrammer.blogspot.com/2013/04/continuous-delivery-part-1-what-is-it.html</link><author>noreply@blogger.com (Jim B)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZbooSyUdfn9Zp-yBG0GRkDEgJH7fkM8s5LkhXaKyalOfAnd6IFYQutdTeMIuJIA1fBAmB5x-6Z35wQWFirBM7GfjrvlQz7x7C18xw37fmPQSEWlz0ILivIUlpDdQmMJWsFihROPGLUGmO/s72-c/build_architecture_development_release.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-5336778117114090657</guid><pubDate>Tue, 12 Mar 2013 19:46:00 +0000</pubDate><atom:updated>2013-03-12T19:46:23.533+00:00</atom:updated><title>Coming soon …</title><description>&lt;p&gt;It has been far too long.&amp;#160; The next series of blogs are are going to cover things I’ve learnt about REST and about HATEOS for mobile:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Custom XML handling for REST services using your own content handler &lt;/li&gt;    &lt;li&gt;Custom JSON handling for REST services using your own content handler &lt;/li&gt;    &lt;li&gt;JSON validation using JSR 303 and XML validation using auto-generated XML schemas &lt;/li&gt;    &lt;li&gt;Super fast writes with a persistence layer &lt;/li&gt;    &lt;li&gt;Memcached clients in java and getting over the 2,500 calls a second barrier on an all-in-one solution. &lt;/li&gt;    &lt;li&gt;Using SNMP4J to alert the outside world &lt;/li&gt;    &lt;li&gt;Modular development and maven plugins &lt;/li&gt;    &lt;li&gt;The REST APIs for Nexus and for Jenkins &lt;/li&gt;    &lt;li&gt;Continuous Delivery &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Phew … &lt;/p&gt;  &lt;p&gt;Its been a while&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2013/03/coming-soon.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-6294507616125954176</guid><pubDate>Sat, 12 Jul 2008 19:24:00 +0000</pubDate><atom:updated>2008-07-12T20:24:01.656+01:00</atom:updated><title>Primary Keys that mean something in Rails</title><description>&lt;p&gt;I like Rails, I really do, but you like me may need to migrate a data-model that doesn&#39;t use locally generated integers as the primary keys (PKs) of entities.&lt;/p&gt;  &lt;p&gt;Rails, by default, seeds model (entity) data with unique identifiers it uses as PKs from database specific mechanisms (say serial columns in PostgreSQL).&lt;/p&gt;  &lt;p&gt;Personally, I think locally generated integers used as identifiers for &amp;quot;things&amp;quot;, are most poor for two main reasons:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;em&gt;They don&#39;t scale&lt;/em&gt;.&amp;#160; Your local postgreSQL instance may just be part of a wider data architecture.&amp;#160; If you use locally generated PKs as Rails will get you to, you&#39;ll clash with other locally (but possibly the same value) PKs from other local DBs when synchronization with the &amp;quot;master&amp;quot; takes place.&amp;#160; If you don&#39;t know what I&#39;m talking about then go look at scaling databases, its not just a postgreSQL issue.&amp;#160; If you really really have/want/need to use an identifier, then there is a good article of using Universal Unique Identifiers (UUID) for IDs at &lt;a href=&quot;http://codesnipers.com/?q=node/143&amp;amp;&amp;amp;title=Using-UUID/GUID-as-Primary-Key-in-Rails&quot;&gt;GUID-as-Primary-in-Rails&lt;/a&gt; although the article doesn&#39;t follow through on how in precise detail, so we&#39;ll cover that in a later blog.&lt;/li&gt;    &lt;li&gt;&lt;em&gt;They don&#39;t mean anything&lt;/em&gt;.&amp;#160; Say for example you have an entity type &lt;em&gt;HillType&lt;/em&gt;, whose PK should really be a unique and meaningful name.&amp;#160;&amp;#160; If you really wanted to find out about the details of a &lt;em&gt;HillType&lt;/em&gt; of name &lt;em&gt;gnarly&lt;/em&gt; you&#39;d want to enter a RESTful-like URL of &lt;em&gt;http://localhost:3000/hilltypes/gnarly&lt;/em&gt;.&amp;#160; You really wouldn&#39;t want to know the mapping between &amp;quot;gnarly&amp;quot; and some internal ID that Rails generated for you via a DB sequence.&amp;#160; Yes, I know there are ways of RESTfulizing the internal ID to some other attribute on the model/table, but avoid the complexity in the first place, and under-populate your database with data it actually needs to be readable by people not frameworks.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So ..........&amp;#160; After those contentious points, how do we do it?&lt;/p&gt;  &lt;h2&gt; Three steps to RAILS CRUD with meaningful PKS&lt;/h2&gt;  &lt;p&gt;1) Unfortunately, I&#39;ve not found a way round of avoiding an integer PK in Rails, unless either you specify your migration without a PK, or you avoid the Rails meta-DDL completely and go native in your migration as in here:-&lt;/p&gt;  &lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; CreateHillTypes &amp;lt; ActiveRecord::Migration
  def self.up
      # -------------------------------
      # This &lt;span class=&quot;kwrd&quot;&gt;is&lt;/span&gt; postgreSQL specific DDL
      # -------------------------------
      execute &amp;lt;&amp;lt;-EOF
        create table &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt;.hill_types (
            typename varchar(255) not &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt; unique,
            description varchar(2000),
            primary key (typename)
        );
      EOF
  end

  def self.down
    drop_table &lt;span class=&quot;str&quot;&gt;&amp;quot;hill_types&amp;quot;&lt;/span&gt;
  end
end&lt;/pre&gt;

&lt;p&gt;2) We also need to ensure our Rails &amp;quot;knows&amp;quot; we&#39;ve provided a non-standard PK, so we need to amend our model:-&lt;/p&gt;

&lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; HillType &amp;lt; ActiveRecord::Base
    set_primary_key &lt;span class=&quot;str&quot;&gt;&amp;quot;typename&amp;quot;&lt;/span&gt;
end&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;3) Next we need to amend the templated controller that &lt;em&gt;script/generate scaffold HillType &lt;/em&gt;generated for us to avoid attempting to mass-assign what is now a protected attribute (typename) on our model.&amp;#160; So, on the &lt;em&gt;create method &lt;/em&gt;Rails makes for you by default in your model controller, you&#39;ll need something like:&lt;/p&gt;

&lt;pre class=&quot;csharpcode&quot;&gt;def create
      @hill_type = HillType.&lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt;
      got_details = &lt;span class=&quot;kwrd&quot;&gt;params&lt;/span&gt;[:hill_type]
      @hill_type.typename = got_details[&lt;span class=&quot;str&quot;&gt;&amp;quot;typename&amp;quot;&lt;/span&gt;]
      @hill_type.description = got_details[&lt;span class=&quot;str&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;]
      respond_to &lt;span class=&quot;kwrd&quot;&gt;do&lt;/span&gt; |format|
          &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; @hill_type.save
              flash[:notice] = &lt;span class=&quot;str&quot;&gt;&#39;HillType was successfully created.&#39;&lt;/span&gt;
              format.html { redirect_to(@hill_type) }
              format.xml  { render :xml =&amp;gt; @hill_type, :status =&amp;gt; :created, :location =&amp;gt; @hill_type }
          &lt;span class=&quot;kwrd&quot;&gt;else&lt;/span&gt;
              format.html { render :action =&amp;gt; &lt;span class=&quot;str&quot;&gt;&amp;quot;new&amp;quot;&lt;/span&gt; }
              format.xml  { render :xml =&amp;gt; @hill_type.errors, :status =&amp;gt; :unprocessable_entity }
          end
      end
  end&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;That is it.&amp;#160; Go gambol in the fields of&amp;#160; meaningful URLs, and leave out meaningless framework convenience identifiers from your models, they are embarrassing. &lt;/p&gt;
&lt;style type=&quot;text/css&quot;&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/07/primary-keys-that-mean-something-in.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-9065703483682239627</guid><pubDate>Thu, 03 Jul 2008 15:42:00 +0000</pubDate><atom:updated>2008-07-03T17:04:57.780+01:00</atom:updated><title>Rails, XHTML and using your own CSS styles</title><description>&lt;p&gt;Got to migrate your CSS and your standard layouts to rails? Read on ......&lt;/p&gt;  &lt;p&gt;A Ruby on Rails (RoR) app holds three key locations you&#39;ll need to know about to re-use your imagery, your Cascading Style Sheet (CSS) look and feel, and your standard layouts.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;em&gt;&amp;lt;project_name&amp;gt;/public/images&lt;/em&gt;: Put your logos and your bits and pieces in terms of iconography in here. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;&amp;lt;project_name&amp;gt;/public/stylesheets&lt;/em&gt;: Put your CSS files (holding all your standard page styling) in here. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;&amp;lt;project_name&amp;gt;/app/views/layout/application.html.erb&lt;/em&gt;: This is where we can define our standard layout to apply for our pages. &lt;/li&gt; &lt;/ol&gt;  &lt;h1&gt;&lt;/h1&gt;  &lt;h2&gt;Standard Layout&lt;/h2&gt;  &lt;p&gt;So, for example, my application.html.erb looks like this:&lt;/p&gt;  &lt;div align=&quot;left&quot;&gt;   &lt;pre class=&quot;csharpcode&quot;&gt;&lt;font size=&quot;1&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;PUBLIC&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;&amp;quot;-//W3C//DTD XHTML 1.1//EN&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;&amp;quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- This is a standard wrapper for all view content --&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;meta&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;Content-Type&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;text/html; charset=UTF-8&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;Sample Rails common layout wrapper&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- Include all our styles as pulled from styles.css --&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;asp&quot;&gt;&amp;lt;%&lt;/span&gt;= stylesheet_link_tag &lt;span class=&quot;str&quot;&gt;&#39;styles&#39;&lt;/span&gt; -&lt;span class=&quot;asp&quot;&gt;%&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- Include all the standard Rails javascript includes --&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;asp&quot;&gt;&amp;lt;%&lt;/span&gt;= javascript_include_tag :defaults -&lt;span class=&quot;asp&quot;&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;wrapper&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- The page content --&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- Standard header to page --&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;header&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;   
                    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;float:left; margin-top:15px;&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;http://timepoorprogrammer.blogspot.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;images/author.png&amp;quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;border-style: none&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- The content that can we&#39;ll change dynamically later --&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;dynamicPanel&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- Yield to whatever local content Rails expects --&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;asp&quot;&gt;&amp;lt;%&lt;/span&gt;= &lt;span class=&quot;kwrd&quot;&gt;yield&lt;/span&gt; -&lt;span class=&quot;asp&quot;&gt;%&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;rem&quot;&gt;&amp;lt;!-- Standard footer to page --&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;footer&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Copyright &lt;span class=&quot;attr&quot;&gt;&amp;amp;copy;&lt;/span&gt; 2008 me&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;style type=&quot;text/css&quot;&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;There are a few things here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The doc type is &lt;em&gt;xhtml&lt;/em&gt;.&amp;#160; If you open this up in Firebug or in HTML Tidy from your Firefox browser (get it if you haven&#39;t already done so), they&#39;ll both tell you this is a full on dynamic HTML page. &lt;/li&gt;

  &lt;li&gt;The &lt;em&gt;javascript_include_tag&lt;/em&gt; is embedded Ruby that ensures your pages include the standard JS files that come with RoR 2.1 &lt;/li&gt;

  &lt;li&gt;The &lt;em&gt;style_sheet_link_tag&lt;/em&gt; points off to the &lt;em&gt;public/stylesheets&lt;/em&gt; location where you put your CSS. &lt;/li&gt;

  &lt;li&gt;The example img tag points off to the &lt;em&gt;public/images&lt;/em&gt; location, yet doesn&#39;t need the public in the actual definition &lt;/li&gt;

  &lt;li&gt;The &lt;em&gt;&amp;lt;%= yield -%&amp;gt;&lt;/em&gt; marker tells RoR to put the content of your views you may have defined or will be defining (under&amp;#160; &lt;em&gt;app/views/&amp;lt;controller_name&amp;gt;&lt;/em&gt; within the standard RoR structure) . &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now go restart your rails, and have a look at your views now, and bask in the fact that they&#39;ll be using your styles and common layout now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you are puzzling over what &lt;em&gt;app/views/controller_name&lt;/em&gt; means and aren&#39;t sure what the names of RoR files should be to express, say controllers, views, models, and how they relate to your RoR file naming conventions and URLs, go look at &lt;a title=&quot;http://peepcode.com/products/rails-from-scratch-part-i&quot; href=&quot;http://peepcode.com/products/rails-from-scratch-part-i&quot;&gt;http://peepcode.com/products/rails-from-scratch-part-i&lt;/a&gt; for a particularly good introduction.&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/07/rails-xhtml-and-using-your-own-css.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-2315463784119423051</guid><pubDate>Thu, 03 Jul 2008 10:03:00 +0000</pubDate><atom:updated>2008-07-03T11:03:26.674+01:00</atom:updated><title>Rails and PostgreSQL for beginners</title><description>&lt;p&gt;I&#39;ve read a few blogs out there on using Ruby on Rails with the very excellent database postgreSQL.&amp;#160; But, I&#39;d not found more than a do the installations and off you go kind of thing.&amp;#160; Given most of the online tutorials assume you click on &amp;quot;About your application&#39;s environment&amp;quot; to ensure all your rails malarky is working okay, I thought it sensible to tell you how.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This blog assumes you have the free Aptana studio for RadRails installed, ruby installed on windows, both the &lt;em&gt;rails&lt;/em&gt; and the &lt;em&gt;postgres-pr&lt;/em&gt; gems installed for ruby, and you&#39;ve got Postgresql up and running on your local box.&amp;#160; Honestly, there are    &lt;br /&gt;a load of online examples of installing Ruby, Rails, Aptana studio, and postgresql for Windows.&amp;#160; I&#39;ll not cover them here. &lt;/p&gt;  &lt;p&gt;1) Start your postgresql server. &lt;/p&gt;  &lt;p&gt;2) Create a directory. &lt;/p&gt;  &lt;p&gt;3) Use Aptana Studio to point to this directory location, choosing &lt;em&gt;postgresql &lt;/em&gt;as the DB of choice, and Aptana will create the basic sub-directory setup for rails you&#39;ll need.&amp;#160; &lt;/p&gt;  &lt;p&gt;4) It will also start the rails server.&amp;#160; &lt;/p&gt;  &lt;p&gt;5) About this time you&#39;ll choosing to view &amp;quot;About your application&#39;s environment&amp;quot; to find out what you&#39;ve got.&amp;#160; This will fail. &lt;/p&gt;  &lt;p&gt;Why?, well when you create a default rails project in Aptana Studio, or any other tool that creates the rails structures you get a default &lt;em&gt;database.yml &lt;/em&gt;in your top level directory, that you can use to setup your DBs with this project.&lt;/p&gt;  &lt;p&gt;But, its default content.&lt;/p&gt;  &lt;p&gt;So ................ &lt;/p&gt;  &lt;p&gt;a) Shutdown your rails server from the Aptana Studio server&#39;s tab, or however else you do it.&lt;/p&gt;  &lt;p&gt;b) Create a file called &lt;em&gt;newdb.bat&lt;/em&gt; in your top level directory of your new project &lt;/p&gt;  &lt;p&gt;Its contents should look alot like:- &lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;font size=&quot;1&quot;&gt;&amp;#160; &lt;/font&gt;&lt;font face=&quot;Courier New&quot;&gt;&lt;font size=&quot;1&quot;&gt;&lt;font color=&quot;#ff0000&quot;&gt;psql -h localhost -U postgres &amp;lt;db\create.sql         &lt;br /&gt; call rake db:migrate&lt;/font&gt; &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This allows you to logon to postgres from the windows command line to create the databases the project requires as defined in an SQL batch file. &lt;/p&gt;  &lt;p&gt;c) This SQL batch file is called &lt;em&gt;create.sql&lt;/em&gt; in your local project db directory, which should look alot (substitute the &lt;em&gt;your_project&lt;/em&gt; and &lt;em&gt;your_username&lt;/em&gt;, and &lt;em&gt;your_password&lt;/em&gt; markers with your own details) like this (in Postgresql format):- &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;font face=&quot;Courier New&quot; color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160; /* Drop and re-create the development database */     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; drop database if exists &amp;lt;your_project&amp;gt;_development;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; create database &amp;lt;your_project&amp;gt;_development       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; with owner = postgres       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; encoding = &#39;UTF8&#39;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; tablespace = pg_default; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160; /* Drop and re-create the test database */     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; drop database if exists &amp;lt;your_project&amp;gt;_test;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; create database &amp;lt;your_project&amp;gt;_test       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; with owner = postgres       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; encoding = &#39;UTF8&#39;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; tablespace = pg_default; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160; /* Drop and re-create the production database */     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; drop database if exists rails_from_scratch_part_one_production;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; create database &amp;lt;your_project&amp;gt;_production       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; with owner = postgres       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; encoding = &#39;UTF8&#39;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; tablespace = pg_default; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160; /* Drop the user if they exist, and re-create them */     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; drop user if exists &amp;lt;your_username&amp;gt;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; create user &amp;lt;your_username&amp;gt; with password &#39;&amp;lt;your_password&amp;gt;&#39;; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160; /* Grant the user all privileges on the databases */     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; grant all privileges on database &amp;lt;your_project&amp;gt;_development to &amp;lt;your_username&amp;gt;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; grant all privileges on database &amp;lt;your_project&amp;gt;_test to &amp;lt;your_username&amp;gt;;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; grant all privileges on database &amp;lt;your_project&amp;gt;_production to &amp;lt;your_username&amp;gt;; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;5) Go to the windows command line.&amp;#160; Navigate to where your &lt;em&gt;newdb.bat&lt;/em&gt; file lives, and run it from there.&amp;#160; This will setup three project databases for you in Postgresql, one for development, one for test, and one for production. &lt;/p&gt;  &lt;p&gt;6) If you have properly installed Postgresql properly, you can check the DB content from your PgAdmin console.&amp;#160; With Rails   &lt;br /&gt;2.1.0 this will create a table called &lt;em&gt;schema_migrations&lt;/em&gt; in each of your three databases.&amp;#160; We&#39;ll come back to this soon once we&#39;ve got tables to make. &lt;/p&gt;  &lt;p&gt;6) Refresh your project in Aptana studio or whatever.&amp;#160; Now restart your server from the server list tab, or however you do it   &lt;br /&gt;and THEN click (or in my case double click) on &amp;quot;About your Application&#39;s environment&amp;quot;.&amp;#160; &lt;/p&gt;  &lt;p&gt;Hey Presto, you will now be presented with the environment, including the development database in which your project resides. &lt;/p&gt;  &lt;p&gt;You are now up and running with postgresql and rails.&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/07/rails-and-postgresql-for-beginners.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-5229149231525248413</guid><pubDate>Mon, 19 May 2008 10:35:00 +0000</pubDate><atom:updated>2008-05-19T11:35:50.428+01:00</atom:updated><title>Finalising WebSVN setup on Windows XP with Cygwin</title><description>&lt;p&gt;You&#39;ve got your WebSVN up and running, but you&#39;ve not got all the features.&amp;#160; Why not? This is because the UI depends on a few programs that usually come with Linux/Unix distributions, and you&#39;ll need to make these available and turn these on for Windows XP.&lt;/p&gt;  &lt;p&gt;So, the final step on Windows XP with WebSVN is to ensure all the tools are available, and here Cygwin will help you out.&lt;/p&gt;  &lt;p&gt;I reckon, Cygwin is something you should probably have on your Windows box anyway, as it allows you to jump between a Unix-like environment and the Windows environment, doing the meaningful stuff as the problem dictates.&amp;#160; Any decent programmer should not need to choose between either flavour of OS tools, justset your box up for both.&lt;/p&gt;  &lt;p&gt;You can pull Cygwin from &lt;a title=&quot;http://www.cygwin.com/&quot; href=&quot;http://www.cygwin.com/, and&quot;&gt;http://www.cygwin.com/, and&lt;/a&gt; the key to setting it up so it has the tools WebSVN needs, is making sure you know how to use the setup installer to pick the right packages.&lt;/p&gt;  &lt;p&gt;WebSVN relies (for its full features) on the following programs being available to the web app users via its file &lt;font face=&quot;Courier New&quot;&gt;websvn/include/config.php&lt;/font&gt;:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font face=&quot;Courier New&quot;&gt;diff&lt;/font&gt;: With this we can enable the full diff functionality for versions of files.&lt;/li&gt;    &lt;li&gt;&lt;font face=&quot;Courier New&quot;&gt;tar &lt;/font&gt;and &lt;font face=&quot;Courier New&quot;&gt;GZip&lt;/font&gt;: With these two we can enable the tarball functionality that allows web users to get a ZIP/TAR of your code.&lt;/li&gt;    &lt;li&gt;&lt;font face=&quot;Courier New&quot;&gt;enscript &lt;/font&gt;and &lt;font face=&quot;Courier New&quot;&gt;sed&lt;/font&gt;: With these two we can enable syntax highlighting on the code in the repositories.&amp;#160; The type of files is defined in &lt;font face=&quot;Courier New&quot;&gt;websvn/include/setup.php&lt;/font&gt;.&amp;#160; You might (like I did) add a couple of entries here for JSP and XML files (say fix them to type HTML) as otherwise these types will be interpreted as plain text which is not great, although this is not something you have to do to get this working.&amp;#160; Its a finishing touch.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Okay. From the cygwin &lt;em&gt;setup &lt;/em&gt;program you get when you download and install it, you specify the set of packages/programs you&#39;ll want to include or add to your new or current Cygwin setup.&amp;#160; You&#39;ll need to include:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;The package &lt;em&gt;diffutils &lt;/em&gt;you&#39;ll find in the &lt;em&gt;utils &lt;/em&gt;section of the cygwin setup program once launched.&lt;/li&gt;    &lt;li&gt;The packages &lt;em&gt;sed, tar, &lt;/em&gt;and &lt;em&gt;gzip &lt;/em&gt;you&#39;ll find in the &lt;em&gt;base &lt;/em&gt;section of the cygwin setup.&lt;/li&gt;    &lt;li&gt;The package &lt;em&gt;enscript &lt;/em&gt;you&#39;ll find in the &lt;em&gt;text &lt;/em&gt;section of the cygwin setup.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Okay, that&#39;s them done.&amp;#160; Clicking thru the cygwin setup will ensure these are installed.&lt;/p&gt;  &lt;p&gt;Once done, you&#39;ll need to configure WebSVN to use these tools.&lt;/p&gt;  &lt;p&gt;Go edit &lt;font face=&quot;Courier New&quot;&gt;websvn/include/config.php&lt;/font&gt; under your &lt;em&gt;htdocs &lt;/em&gt;location, and uncomment the appropriate lines to point to where these tools now reside.&amp;#160; My local file looks like this (it depends on where you installed cygwin too of course):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;// We are not a linux box so we need to use        &lt;br /&gt;// cygwin toolkit exes&lt;/font&gt;&lt;font face=&quot;Courier New&quot;&gt;&amp;#160; &lt;br /&gt;$config-&amp;gt;setDiffPath(&amp;quot;C:\\cygwin\\bin&amp;quot;);        &lt;br /&gt;$config-&amp;gt;setTarPath(&amp;quot;C:\\cygwin\\bin&amp;quot;);        &lt;br /&gt;$config-&amp;gt;setGZipPath(&amp;quot;C:\\cygwin\\bin&amp;quot;); &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;// For syntax colouring, if option enabled...       &lt;br /&gt;$config-&amp;gt;setEnscriptPath(&amp;quot;C:\\cygwin\\bin&amp;quot;);        &lt;br /&gt;$config-&amp;gt;setSedPath(&amp;quot;C:\\cygwin\\bin&amp;quot;);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt; and make sure you enable the download feature by uncommenting:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;$config-&amp;gt;allowDownload();&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;and enable the colourisation/syntax highlighting of files by uncommenting:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;#160;&lt;font face=&quot;Courier New&quot;&gt;$config-&amp;gt;useEnscript();&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now go startup the svn service, and startup apache from your XAMPP console (see previous blogs).&lt;/p&gt;  &lt;p&gt;Go view the results, as now you&#39;ll have syntax highlighted, downloadable, and diff-able code at your local repo home &lt;a href=&quot;http://localhost/websvn&quot;&gt;http://localhost/websvn&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Done.&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/05/finalising-websvn-setup-on-windows-xp.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-8168816471107330600</guid><pubDate>Wed, 14 May 2008 20:02:00 +0000</pubDate><atom:updated>2008-05-14T21:02:58.387+01:00</atom:updated><title>Pretty-up your SVN repositories via the web with XAMPP</title><description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Much of this is taken from the great blog entry at &lt;a href=&quot;http://turnleft.inetsolution.com/2007/07/how_to_setup_subversion_apache_1.html&quot;&gt;http://turnleft.inetsolution.com/2007/07/how_to_setup_subversion_apache_1.html&lt;/a&gt;, but with an XAMPP slant, so apologies for any repetition here. &lt;/p&gt;  &lt;p&gt;No time?, read on:&lt;/p&gt;  &lt;p&gt;1) Get and install XAMPP 1.6.3a as it comes with Apache 2.2.x.&amp;#160; This is big enough to be the topic of a separate thread.&amp;#160; But you shouldn&#39;t go far wrong if you follow the guide at &lt;a href=&quot;http://www.apachefriends.org/en/xampp-windows.html&quot;&gt;http://www.apachefriends.org/en/xampp-windows.html&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;2) Augment the XAMPP version of apache 2.2 with the Subversion specific libraries needed, available in the file &lt;font face=&quot;Courier New&quot;&gt;svn-win32-1.4.6.zip&lt;/font&gt; you can get at &lt;a href=&quot;http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91&amp;amp;expandFolder=91&amp;amp;folderID=74&quot;&gt;http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91&amp;amp;expandFolder=91&amp;amp;folderID=74&lt;/a&gt;.&amp;#160; Do the following: &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; a) Stop apache from your XAMPP control panel &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; b) XAMPP has invalid pre-provided files &lt;font face=&quot;Courier New&quot;&gt;mod_dav_svn.so&lt;/font&gt; and &lt;font face=&quot;Courier New&quot;&gt;mod_authz_svn.so&lt;/font&gt; modules in &lt;font face=&quot;Courier New&quot;&gt;xampp\apache\modules&lt;/font&gt;, replace them with the correct ones you&#39;ll find in the zip. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; c) XAMPP may come with invalid DLL for svn. Just in case, replace &lt;font face=&quot;Courier New&quot;&gt;xampp\apache\bin\libdb44.dll&lt;/font&gt; and &lt;font face=&quot;Courier New&quot;&gt;xampp\apache\bin\int13_svn.dll&lt;/font&gt; with the ones you&#39;ll find in the zip. &lt;/p&gt;  &lt;p&gt;3) Now, configure your repository for web access via Apache.&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; a) Edit &lt;font face=&quot;Courier New&quot;&gt;C:\xampp\apache\conf\httpd.conf&lt;/font&gt; and add: &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font face=&quot;Courier New&quot;&gt;Include conf/extra/httpd-subversion.conf&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; b) Create &lt;font face=&quot;Courier New&quot;&gt;http-subversion.conf&lt;/font&gt; in the &lt;font face=&quot;Courier New&quot;&gt;extra&lt;/font&gt; subdirectory.&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; c) Populate it with details of your repository, and ensure the amended modules get loaded: &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font face=&quot;Courier New&quot;&gt;LoadModule authz_svn_module modules/mod_authz_svn.so     &lt;br /&gt;&amp;#160;&amp;#160; LoadModule dav_svn_module modules/mod_dav_svn.so &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Location /svn/prototypes&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DAV svn      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SVNPath c:/svn/prototypes      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AuthType Basic      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Options FollowSymLinks      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; order allow,deny      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; allow from all      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AuthName &amp;quot;prototypes&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AuthUserFile c:/svn/passwords      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Require valid-user      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Location&amp;gt;&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;4) Create the common web access password file for the repositories, and add a user. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font face=&quot;Courier New&quot;&gt;&amp;lt;path_to_htpasswd_under_xampp&amp;gt; -cb &amp;lt;path_to_svn_root_directory_less_drive_handle&amp;gt; &amp;lt;username&amp;gt; &amp;lt;password&amp;gt; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; e.g. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font face=&quot;Courier New&quot;&gt;c:\xampp\apache\bin\htpasswd -cb \svn\passwords whoever weRst194UUd &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;5) Check how we are doing by viewing the repositories over webDAV, by starting Apache again from the XAMPP control panel, and view the repository at &lt;a href=&quot;http://localhost/svn/&quot;&gt;&lt;font face=&quot;Courier New&quot;&gt;http://localhost/svn/&lt;/font&gt;&lt;/a&gt;&lt;font face=&quot;Courier New&quot;&gt;&amp;lt;repository_name&amp;gt;.&lt;/font&gt;&amp;#160; You will now need to use the user name and password to access your repository. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; So we are talking two password files, one under &lt;font face=&quot;Courier New&quot;&gt;C:\&amp;lt;svn_root&amp;gt;\&amp;lt;repository_name&amp;gt;\conf\passwd&lt;/font&gt; for configuring SVN repository users who do checkouts etc etc on a particular repository, and one for all the online users who can browse repositories in &lt;font face=&quot;Courier New&quot;&gt;C:\&amp;lt;svn_root&amp;gt;\passwords&lt;/font&gt; via using htpasswd generation above. &lt;/p&gt;  &lt;p&gt;6) But wait, what about the pretty-up bit you promised? For this you&#39;ll need to stop using straight webDAV to display your repositories as its ugly.&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; a) Note the &amp;quot;extra&amp;quot; stuff we added to the httpd-subversion.conf:- &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font face=&quot;Courier New&quot;&gt;Options FollowSymLinks     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; order allow,deny      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; allow from all &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; This is for our choice of repository web front end, &lt;font face=&quot;Courier New&quot;&gt;WebSVN 2.0.&lt;/font&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; b) Ensure XAMPP Apache has the full PHP support needed for our choice of repository web front end. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; i) You can get PHP from &lt;a href=&quot;http://www.php.net/downloads.php&quot;&gt;http://www.php.net/downloads.php&lt;/a&gt;, go for the 5.2.6 windows installer, as its got the fixes missing in the build a few days earlier. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ii) During install, select the Apache 2.2.x Module that allows the installer to update your httpd.conf file for XAMPP with the appropriate settings. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; c) Download the most recent ZIP package of WebSVN 2.0 from &lt;a href=&quot;http://websvn.tigris.org/servlets/ProjectDocumentList&quot;&gt;http://websvn.tigris.org/servlets/ProjectDocumentList&lt;/a&gt;. Unpack the files into xampp\htdocs and rename to websvn &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; d) Finish the job by configuring WebSVN.&amp;#160; Rename &lt;font face=&quot;Courier New&quot;&gt;xampp\htdocs\websvn\include\distconfig.inc&lt;/font&gt; to &lt;font face=&quot;Courier New&quot;&gt;config.inc&lt;/font&gt;, and tell WebSVN its dealing with a windows host, and where the original svn &amp;quot;root&amp;quot; location under which all your repositories live happens to be, so uncomment and amend the entries: &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $config-&amp;gt;setServerIsWindows();   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $config-&amp;gt;parentPath(&amp;quot;c:\\&amp;lt;path_to_your_svn_root&amp;gt;&amp;quot;); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; e) Restart Apache, and you should now be able to access &lt;a href=&quot;http://localhost/websvn&quot;&gt;http://localhost/websvn&lt;/a&gt; to see all the repositories under your svn root using the nice display from the WebSVN people.&lt;/p&gt;  &lt;p&gt;Done.&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/05/pretty-up-your-svn-repositories-via-web.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-482074926167719194</guid><pubDate>Tue, 13 May 2008 15:42:00 +0000</pubDate><atom:updated>2008-05-13T16:42:00.956+01:00</atom:updated><title>Subversion on Windows XP</title><description>&lt;p&gt;This entry is if you need to setup a subversion code repository for managing your code on a Windows XP box:&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;1) Run the EXE (svn-1.4.6-setup.exe found at &lt;a href=&quot;http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91&amp;amp;expandFolder=91&amp;amp;folderID=74)&quot;&gt;Get the EXE&lt;/a&gt; to install Subversion &lt;/p&gt;  &lt;p&gt;2) Issue the repository creation commands from the Windows command line wherever you want to make your repository:   &lt;br /&gt;a) &lt;font face=&quot;Courier New&quot;&gt;mkdir svn&lt;/font&gt;    &lt;br /&gt;b) &lt;font face=&quot;Courier New&quot;&gt;svnadmin create c:&amp;lt;path to svn&amp;gt;\repos&lt;/font&gt; to create the fundamental repository structure &lt;/p&gt;  &lt;p&gt;3) Create the subversion Windows service &lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;sc create svn binPath= &amp;quot;\&amp;quot;C:\Program Files\Subversion\bin\svnserve.exe\&amp;quot; --service -r C:\&amp;lt;path to svn&amp;gt;&amp;quot; DisplayName= &amp;quot;Subversion Server&amp;quot; depend= Tcpip start= auto&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;4) Start the subversion Windows service, either from the command line with &amp;quot;&lt;font face=&quot;Courier New&quot;&gt;net start svn&lt;/font&gt;&amp;quot; or from the services listing in Control Panel. &lt;/p&gt;  &lt;p&gt;5) Go and remove the anonymous access from the repository conf directory file &lt;font face=&quot;Courier New&quot;&gt;C:\&amp;lt;path to svn&amp;gt;\repos\conf\svnserve.conf&lt;/font&gt;, uncomment these lines and change anon-access to none: &lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;anon-access = none     &lt;br /&gt;auth-access = write      &lt;br /&gt;password-db = passwd      &lt;br /&gt;realm = My Subversion Repository&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;6) Add some users who can get at the repository, by editing &lt;font face=&quot;Courier New&quot;&gt;C:\&amp;lt;path to svn&amp;gt;\repos\conf\passwd&lt;/font&gt;, in the format: &lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;username = userpassword&lt;/font&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;7) Check the service is working from some directory from the windows command line tool using the command: &lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;svn checkout svn://localhost/repos &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;It should ask you for your password, and will create your local copy of repos&lt;/p&gt;  &lt;p&gt;Done.&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/05/subversion-on-windows-xp.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-2017075340480708685</guid><pubDate>Fri, 09 May 2008 11:50:00 +0000</pubDate><atom:updated>2008-05-09T12:50:13.170+01:00</atom:updated><title>Easy Blogging</title><description>&lt;p&gt;Need a quick way to post your blog? &lt;/p&gt;  &lt;p&gt;No time to write custom HTML that fits the blog provider templates?.&amp;#160; No time to battle with say the &lt;em&gt;blogger.com&lt;/em&gt; posting editor&#39;s occasional habit of inserting HTML where you don&#39;t want it to, or saving when you don&#39;t want it to?. No time to figure out what fonts, layout, and setup you need?&lt;/p&gt;  &lt;p&gt;No problem.&lt;/p&gt;  &lt;p&gt;Download the latest version of Windows Live Writer. It will walk you through the install process, asking you where your blog is, picking up the styles and layout it needs from &lt;em&gt;blogger.com&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;This will configure the Weblog settings.&lt;/p&gt;  &lt;p&gt;Next open Live Writer, write your entry, and hit Publish.&lt;/p&gt;  &lt;p&gt;Done.&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/05/easy-blogging.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3413472902245248871.post-7925683972873979155</guid><pubDate>Tue, 06 May 2008 00:06:00 +0000</pubDate><atom:updated>2008-05-06T01:06:17.401+01:00</atom:updated><title>How to JPA outside your JEE container: Part 1: The Basics</title><description>&lt;h1&gt;1) Introduction&lt;/h1&gt;  &lt;p&gt;Over the past 10 years, numerous persistence frameworks have been developed for Java.&amp;#160; Each of these frameworks have lead to various implementations, each of which have addressed particular issues well, but this stew of activity has resulted in many different, and divergent paths to solve what is a common problem, persisting data to back-end storage.&lt;/p&gt;  &lt;p&gt;The Java Persistence API (JPA) attempts to standardize this multiplicity.&amp;#160; &lt;/p&gt;  &lt;p&gt;Implementations of the JPA standard are already available from a variety of providers, including Sun (Glassfish JPA), BEA (Kodo), Oracle (TopLink), RedHat/JBoss (Hibernate EntityManager), IBM Websphere 6.1 (EJB3 service pack since December 2007), Tangasol Coherence (Cache Store), OpenJPA, and JPOX, to name a few.&lt;/p&gt;  &lt;p&gt;This blog entry is the first in a series covering the basics of JPA, ready for the next entries which will cover implementation of JPA outside a JEE container, and the final entry caching and database HA with the JPA.&lt;/p&gt;  &lt;h1&gt;2) Key Concepts&lt;/h1&gt;  &lt;p&gt;There are several key concepts to cover when using JPA to persist and retrieve data.&amp;#160; This section briefly discussed each in turn. &lt;/p&gt;  &lt;p&gt;Skip this blog entry if you know your JPA already.&lt;/p&gt;  &lt;p&gt;All of the concepts identified here can be read up on in detail in &lt;em&gt;EJB3 in Action&lt;/em&gt; chapters 6 to 11, and in extreme detail in the whole of &lt;em&gt;Java Persistence with Hibernate&lt;/em&gt;. &lt;/p&gt;  &lt;h2&gt;The Entity Manager &lt;/h2&gt;  &lt;p&gt;A Java application using the JPA does not interact with data storage directly via JDBC connections instead the main interface any layer above the JPA uses is the EntityManager, as defined at &lt;a href=&quot;http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html&quot;&gt;http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;The EntityManager interface is used to support Create, Retrieve, Update, and Delete (CRUD) data actions and custom query actions on object data.&lt;/p&gt;  &lt;p&gt;Probably the clearest description of the purpose of the methods on an EntityManager instance is in Chapter 9 Manipulating Entities with EntityManager of Java Persistence with Hibernate. &lt;/p&gt;  &lt;p&gt;Here, we&amp;#8217;ll use example code to clarify the concepts this reference discusses. &lt;/p&gt;  &lt;p&gt;Here is example usage of an (out-of-container, namely outside JBoss) EntityManager instance.&amp;#160; Here an EntityManager is used to save the details of a Book: &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;void addBook(Book a_Book) throws MyException      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EntityTransaction currentTrans = null;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; final EntityManager em = super.getEntityManager();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; currentTrans = em.getTransaction();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; currentTrans.begin();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; em.persist(a_Book);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; currentTrans.commit();&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch (Exception anyE)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (currentTrans.isActive())       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; currentTrans.rollback();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new MyException(errorMessage, anyE);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&lt;/font&gt;Within the example, the call to the method persist is used when adding new data via the EntityManager instance. &lt;/p&gt;  &lt;p&gt;Which EntityManager method is applicable for what purpose needs to be explained by reference to the life-cycle of a typical JEE Entity.&amp;#160; This is identified in the next section. &lt;/p&gt;  &lt;p&gt;Note: For JavaDoc for the persistence API look under the package javax.persistence at &lt;a href=&quot;http://java.sun.com/javaee/5/docs/api/&quot;&gt;http://java.sun.com/javaee/5/docs/api/&lt;/a&gt; .&amp;#160;&amp;#160; &lt;/p&gt;  &lt;h2&gt;Entities &lt;/h2&gt;  &lt;p&gt;An application views or traverses data in data storage indirectly, via abstractions known as JEE Entities. &lt;/p&gt;  &lt;h3&gt;Annotations &lt;/h3&gt;  &lt;p&gt;JEE Entities and the relationships between them are defined by annotations applied within Java classes, and these Entities are used to map to the relational schema of the data storage. &lt;/p&gt;  &lt;p&gt;From the example code in the previous section, the book entity (Book.java) is defined by the following code, which exhibits common annotations which you will see repeated throughout the entity definitions within the example application: &lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;package com.whatever.example.dao.entities; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;import com.whatever.dao.UniqueIDGenerator;      &lt;br /&gt;import java.util.Date;       &lt;br /&gt;import java.util.HashSet;       &lt;br /&gt;import java.util.Set;       &lt;br /&gt;import javax.persistence.CascadeType;       &lt;br /&gt;import javax.persistence.Column;       &lt;br /&gt;import javax.persistence.Entity;       &lt;br /&gt;import javax.persistence.FetchType;       &lt;br /&gt;import javax.persistence.Id;       &lt;br /&gt;import javax.persistence.JoinColumn;       &lt;br /&gt;import javax.persistence.ManyToOne;       &lt;br /&gt;import javax.persistence.OneToMany;       &lt;br /&gt;import javax.persistence.Table; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;/**      &lt;br /&gt;* Book Entity       &lt;br /&gt;*       &lt;br /&gt;* @author jball       &lt;br /&gt;*/       &lt;br /&gt;@Entity       &lt;br /&gt;@Table(name = &amp;quot;book&amp;quot;, schema = &amp;quot;public&amp;quot;)       &lt;br /&gt;public class Book implements java.io.Serializable       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** Size of DATE field */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private static final int SIZE_OF_DATE_FIELD = 29;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** Size of BIG field */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private static final int SIZE_OF_BIG_FIELD = 2000;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** Book UUID */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private String m_Bookuuid;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** Category */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private Category m_Category;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** Library */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private Library m_Library;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** title */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private String m_Title;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** author */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private String m_Author;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** published */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private Date m_Published;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** description */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private String m_Description;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /** on loan records */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private Set&amp;lt;OnLoan&amp;gt; m_OnLoans = new HashSet&amp;lt;OnLoan&amp;gt;(0); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160; /**      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Default empty constructor       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Book()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Kitchen sink constructor.&amp;#160; Note the entity makes its own       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * identifier which is a distributed storage safe UUID.       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Title title       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Author author       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Published published date       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Description description       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Category category       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Library library       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Book(String a_Title,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; String a_Author,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Date a_Published,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; String a_Description,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Category a_Category,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Library a_Library)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Bookuuid&amp;#160;&amp;#160;&amp;#160; = UniqueIDGenerator.getID();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Title&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = a_Title;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Author&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; = a_Author;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Published&amp;#160;&amp;#160; = a_Published;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Description = a_Description;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Category&amp;#160;&amp;#160;&amp;#160; = a_Category;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Library&amp;#160;&amp;#160;&amp;#160;&amp;#160; = a_Library;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the PK       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return PK       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @Id       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @Column(name = &amp;quot;bookuuid&amp;quot;, unique = true, nullable = false)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public String getBookuuid()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_Bookuuid;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set the PK       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Bookuuid PK       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setBookuuid(String a_Bookuuid)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Bookuuid = a_Bookuuid;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the book category       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return Book Category       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @ManyToOne(fetch = FetchType.LAZY)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @JoinColumn(name = &amp;quot;categoryname&amp;quot;, nullable = false)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Category getCategory()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_Category;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set the Book Category       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Category Book Category       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setCategory(Category a_Category)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Category = a_Category;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the book&#39;s library       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return Library that holds book       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @ManyToOne(fetch = FetchType.LAZY)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @JoinColumn(name = &amp;quot;libraryuuid&amp;quot;, nullable = false)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Library getLibrary()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_Library;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set the book&#39;s library       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Library Library       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setLibrary(Library a_Library)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Library = a_Library;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the book title       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return Book title       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @Column(name = &amp;quot;title&amp;quot;, nullable = false)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public String getTitle()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_Title;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set the book title       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Title book title       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setTitle(String a_Title)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Title = a_Title;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the book author       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return book author       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @Column(name = &amp;quot;author&amp;quot;, nullable = false)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public String getAuthor()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_Author;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set the book author       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Author Book Author       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setAuthor(String a_Author)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Author = a_Author;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the published date       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return published date       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @Column(name = &amp;quot;published&amp;quot;, nullable = false,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; length = SIZE_OF_DATE_FIELD)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Date getPublished()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_Published;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set published date       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Published published date       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setPublished(Date a_Published)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Published = a_Published;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the book description       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return book description       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @Column(name = &amp;quot;description&amp;quot;, nullable = false,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; length = SIZE_OF_BIG_FIELD)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public String getDescription()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_Description;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set the book description       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_Description book description       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setDescription(String a_Description)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_Description = a_Description;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Get the on loan details for the book       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @return on loan details       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; mappedBy = &amp;quot;book&amp;quot;)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public Set&amp;lt;OnLoan&amp;gt; getOnLoans()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.m_OnLoans;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; /**       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * Set the on loan details       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; *       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; * @param a_OnLoans on loan details       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; */       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void setOnLoans(Set&amp;lt;OnLoan&amp;gt; a_OnLoans)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.m_OnLoans = a_OnLoans;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;There are several key features in this code:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The @Entity annotation marks the class definition as a JEE Entity which can be managed via the JPA EntityManager.      &lt;br /&gt;The @Table annotation is not mandatory.&amp;#160; It is suggested you use it, as it ensures any RDBMS table creation actions the JPA EntityManagerFactory may perform on your behalf (see the persistence unit section below) results in the correct mapping between the object layer and the relational layer. &lt;/li&gt;    &lt;li&gt;The @Id field is used to identify the unique identifier or primary key for an instance of entity type Book.&amp;#160; In our example code here, the code uses a custom UUID generator for the primary key.&amp;#160; This is a by-product of our example also being used for a multi-database instance example illustrating HA-JDBC failover which will be described in a later blog.&amp;#160; There are many strategies that can be used to generate the unique ID, either your own custom code, or get the JPA provider to do it for you, or rely on the background data storage to do it for you (say via a database sequence).&amp;#160; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The annotations that can be used for ID generation are discussed in some detail in section 4.2.3 &lt;em&gt;Database Primary Keys&lt;/em&gt; of &lt;em&gt;Java Persistence with Hibernate&lt;/em&gt;.&amp;#160; Make sure you choose an ID generation strategy that scales and de-couples the JPA from the DB implementation properly; we reckon the less dependent the method is on a particular database implementation the better, as otherwise you can end up in danger of producing a JPA persistence layer that only works with one type of database, which misses the point of the JPA.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Every attribute you want stored against an entity needs a setter and a getter method.&amp;#160; These take the form of setters and getters throughout Java, namely get&amp;lt;Attribute&amp;gt; and set &amp;lt;Attribute&amp;gt; where &amp;lt;Attribute&amp;gt; corresponds to the attribute name starting with an upper case letter.&amp;#160; You can leave it to the JPA to decide what the actual database column names should be, but, in our pedantic example the @Column annotation specifies all the database column characteristics we consider important, all of them. &lt;/li&gt;    &lt;li&gt;The relationship between one entity and another can be expressed via the annotations @OneToOne, @OneToMany, @ManyToOne, and @ManyToMany.&amp;#160; The @OneToMany annotation in the example code above indicates there is a relationship between a Book entity and an OnLoan Entity, where a book may have been on loan to many different members over any particular time frame.&amp;#160; Be advised that there are many different argument permutations allowable for these relationship annotations.&amp;#160; In the example here, the arguments to the annotation indicate the cascade type is ALL, and the fetch type is LAZY.&amp;#160; This means if we delete a Book entity, the JPA will cascade delete any OnLoan records that refer to the Book, and the LAZY means the JPA will only perform SQL required to retrieve OnLoan records when an application with a handle on the Book object actually invokes the getOnLoans method. &lt;/li&gt;    &lt;li&gt;All the JPA entities should implement Serializable to avoid &amp;#8220;between-tier&amp;#8221; transport issues in multi-tier multi-box applications. &lt;/li&gt;    &lt;li&gt;All the JPA entities should contain a default empty constructor.&amp;#160; We&amp;#8217;ve discovered that this constructor is used behind the scenes by the Hibernate JPA implementation to help maintain the correct entity content.&amp;#160; Without it, entities do not get properly hydrated by the Hibernate JPA provider on data retrieval. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Lifecycle &lt;/h3&gt;  &lt;p&gt;All Entities within the JPA architecture have a life-cycle, best described in section 9.1: &lt;em&gt;The persistence lifecycle&lt;/em&gt; in &lt;em&gt;EJB3 in Action&lt;/em&gt;.&amp;#160; This life-cycle is what explains the methods on an EntityManager instance.&amp;#160; We&#39;ll cover it really briefly here, but please refer to the reference documentation for detail. &lt;/p&gt;  &lt;p&gt;Entities start in a New state, and this state represents their condition just after construction.    &lt;br /&gt;When an entity is passed to the persist method on an EntityManager it moves to the Managed state, and the data representation of it is scheduled to be added to data storage. Managed entities are also returned from an EntityManager that executes either a query or the find operation. &lt;/p&gt;  &lt;p&gt;In this managed state, an application can navigate the relationships expressed in the entity method signatures, so for example the call getOnLoans on an object of type Book would result in the JPA retrieving the OnLoan records for the book. &lt;/p&gt;  &lt;p&gt;When an entity moves outside of the scope of the EntityManager that is looking after it (which can occur if the EntityManager has been closed, the entity has been passed between tiers in a multi-tier application, or the entity has been passed between threads) the entity will move to the Detached state.&amp;#160; &lt;/p&gt;  &lt;p&gt;You can amend the content of a detached entity by setting its values, but the content of this object needs to be merged back to back-end storage.&amp;#160; Our example code provided always uses the merge operation on amended entity data which is posted back to data storage to cover detachment scenarios.&amp;#160; It is suggested you follow the same pattern to avoid Detached Entity passed to merge/persist messages from the JPA provider layer. &lt;/p&gt;  &lt;p&gt;The merge operation schedules the content of an entity to be updated in data storage.    &lt;br /&gt;An Entity can be removed using the remove method, which schedules the persistence provider to delete the representation in the data storage.     &lt;br /&gt;Note: Please note the scheduled to comment with respect to add, update, and delete actions.&amp;#160; The actual operations get performed by the Hibernate implementation of the JPA when the EntityManager is made to commit a transaction either by you or by the provider when it flushes. &lt;/p&gt;  &lt;h2&gt;The Persistence Unit &lt;/h2&gt;  &lt;p&gt;The Java classes defining JEE Entities need to be grouped together into their own JAR and this is known as a persistence unit.&amp;#160; An application can have many persistence units, and each persistence unit can be configured independently to use different back end storage. &lt;/p&gt;  &lt;p&gt;It is sensible to organize your persistence unit to cover a particular relational data-model or object domain model that expresses the data scope of your solution.&amp;#160; There is usually no point in breaking up a single logical data model into multiple persistence units. &lt;/p&gt;  &lt;p&gt;Each persistence unit JAR keeps its classes at the top level of the JAR. &lt;/p&gt;  &lt;p&gt;A persistence unit also needs a configuration file called &lt;em&gt;persistence.xml&lt;/em&gt; that defines the entity content of the persistence unit and the way in which the persistence unit relates to the relational data model.&amp;#160; In our example code, the content of &lt;em&gt;META-INF/persistence.xml&lt;/em&gt; ensures that the application creates the database schema it needs from the JPA entity annotations it has if said schema is missing, or just uses the one already there.&amp;#160; So JPA gives you a way of creating schema in any database without writing the DDL. &lt;/p&gt;  &lt;p&gt;Here is the file for our sample persistence unit:&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;lt;persistence&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;persistence-unit name=&amp;quot;libraryDAO&amp;quot; &lt;/font&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;transaction-type=&amp;quot;RESOURCE_LOCAL&amp;quot;&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;!-- Add one entry per Entity class in the JAR --&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;class&amp;gt;com.example.dao.entities.Book&amp;lt;/class&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;class&amp;gt;com.example.dao.entities.Category&amp;lt;/class&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;class&amp;gt;com.example.dao.entities.Library&amp;lt;/class&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;class&amp;gt;com.example.dao.entities.Member&amp;lt;/class&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;class&amp;gt;com.example.dao.entities.OnLoan&amp;lt;/class&amp;gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;lt;class&amp;gt;com.example.dao.entities.OnLoanId&amp;lt;/class&amp;gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;!-- Hibernate properties --&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;properties&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.ejb.cfgfile&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; value=&amp;quot;hibernate.cfg.xml&amp;quot;/&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.hbm2ddl.auto&amp;quot; value=&amp;quot;update&amp;quot;/&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/properties&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/persistence-unit&amp;gt;       &lt;br /&gt;&amp;lt;/persistence&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The transaction type defines the transaction type of the unit.&amp;#160; Ours is RESOURCE_LOCAL because it does not make use of the Java Transaction API (JTA) that could have been used if this persistence unit had been deployed under JBoss.    &lt;br /&gt;Our persistence unit doesn&amp;#8217;t need a JEE container to run, so doesn&amp;#8217;t make use of JTA.&amp;#160; RESOURCE_LOCAL is a short way of indicating to the JPA provider to use the default JDBC transaction model. &lt;/p&gt;  &lt;p&gt;The &lt;em&gt;hibernate.ejb.cfgfile&lt;/em&gt; setting allows us to get the JPA provider to obtain the variable part of the configuration of the persistence unit (say the connection details) from a file that lives in the class path of the application outside the persistence unit JAR boundary.&amp;#160; This file is called &lt;em&gt;hibernate.cfg.xml&lt;/em&gt; and is discussed later.&lt;/p&gt;  &lt;h2&gt;Transactions &lt;/h2&gt;  &lt;p&gt;All entity adding/deleting/altering actions need to be encapsulated in transactions within the JPA.&amp;#160; Within our outside-a-container implementation in the example code, the transactions bound all the operations performed by an EntityManager instance.&amp;#160; So, repeating a code snippet previously given, the code highlighted in red represents the transaction management for an add operation:&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;public void addBook(Book a_Book) throws DAOException      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color=&quot;#ff0000&quot;&gt;EntityTransaction currentTrans = null;        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; final EntityManager em = super.getEntityManager();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color=&quot;#ff0000&quot;&gt;currentTrans = em.getTransaction();        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color=&quot;#ff0000&quot;&gt;currentTrans.begin();        &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; em.persist(a_Book);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color=&quot;#ff0000&quot;&gt;currentTrans.commit();&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch (Exception anyE)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color=&quot;#ff0000&quot;&gt;if (currentTrans.isActive())        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; currentTrans.rollback();         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }         &lt;br /&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new DAOException(errorMessage, anyE);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As can be seen, this transaction management code represents a significant part of the code, which unfortunately is the case when you use the JPA outside a JEE container.&amp;#160; &lt;/p&gt;  &lt;p&gt;Outside a JEE container you are responsible in your own code for identifying the beginning of a &lt;em&gt;unit of work&lt;/em&gt; with a &lt;em&gt;transaction.begin&lt;/em&gt; statement, and indicating when this unit of work is complete with a &lt;em&gt;transaction.commit&lt;/em&gt; or &lt;em&gt;transaction.rollback&lt;/em&gt; statement.&lt;/p&gt;  &lt;h2&gt;Complex Queries &lt;/h2&gt;  &lt;p&gt;In most cases, you can navigate the object model of the data returned from an EntityManager.find operation to get hold of the data you may need from the object&amp;#8217;s get methods.&amp;#160; &lt;/p&gt;  &lt;p&gt;Sometimes you&amp;#8217;ll need more power than this interface offers.&amp;#160; To get more power, you need to create custom queries, which can be defined in the query language JPQL. &lt;/p&gt;  &lt;p&gt;These custom queries can form part of the entity classes themselves, or can be in a file.&amp;#160; We chose the file route as it then means we know where to go to alter our queries without altering code. &lt;/p&gt;  &lt;p&gt;Custom queries are scoped to a particular persistence unit by defining an &lt;em&gt;orm.xml&lt;/em&gt; file embedded inside the persistence unit at the same directory location as the &lt;em&gt;persistence.xml&lt;/em&gt;. &lt;/p&gt;  &lt;p&gt;Here is the &lt;em&gt;orm.xml&lt;/em&gt; for our example code: &lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;      &lt;br /&gt;&amp;lt;entity-mappings xmlns=&amp;quot;&lt;/font&gt;&lt;a href=&quot;http://java.sun.com/xml/ns/persistence/orm&quot; ?=&quot;?&quot;&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;http://java.sun.com/xml/ns/persistence/orm&amp;quot;&lt;/font&gt;&lt;/a&gt;     &lt;br /&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xmlns:xsi=&amp;quot;&lt;/font&gt;&lt;a href=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; ?=&quot;?&quot;&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;/font&gt;&lt;/a&gt;     &lt;br /&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; xsi:schemaLocation=&amp;quot;&lt;/font&gt;&lt;a href=&quot;http://java.sun.com/xml/ns/persistence/orm&quot;&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;http://java.sun.com/xml/ns/persistence/orm&lt;/font&gt;&lt;/a&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt; &lt;/font&gt;&lt;a href=&quot;http://java.sun.com/xml/ns/persistence/orm_1_0.xsd&quot; ?=&quot;?&quot;&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;http://java.sun.com/xml/ns/persistence/orm_1_0.xsd&amp;quot;&lt;/font&gt;&lt;/a&gt;     &lt;br /&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; version=&amp;quot;1.0&amp;quot;&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getAllBooks&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from Book b order by b.title asc       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getBookByTitle&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from Book b       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where b.title = :bookTitle       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getAllCategories&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from Category c order by c.categoryname asc       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getAllLibraries&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from Library l order by l.name asc       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getAllMembers&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from Member m order by m.fullname asc       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getMemberByName&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from Member m       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where m.fullname = :memberName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getAllLoans&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from OnLoan ol order by ol.member.fullname asc       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getLoansForMember&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from OnLoan ol       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where ol.id.memberuuid = :memberID       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;named-query name=&amp;quot;getLoansForLibrary&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; from OnLoan ol       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; where ol.member.library.libraryuuid = :libraryID       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/query&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/named-query&amp;gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;lt;/entity-mappings&amp;gt; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Each query identified within the file is of type named-query.&amp;#160; This is useful in-so-far as you can amend the caching properties of these queries to prevent them from hitting the database each time they are run, and by presenting them as named queries, the EntityManagerFactory will pre-compile these on initial startup for speedy usage. &lt;/p&gt;  &lt;p&gt;The CDATA tag allows us to embed unruly characters in the query statements if we need to do, to avoid any XML processing errors. &lt;/p&gt;  &lt;p&gt;Each query statement uses the Entity class names rather than the database tables names, and uses the attribute names defined in get&amp;lt;Attribute&amp;gt; and set&amp;lt;Attribute&amp;gt; on the Entity classes instead of table columns.&amp;#160; Make sure you ensure the first character of the attribute names used in the orm.xml is lower case, unlike the access methods on the Entity class. &lt;/p&gt;  &lt;p&gt;A query statement can use placeholders for variable data, an example placeholder being &lt;em&gt;:libraryID&lt;/em&gt; in the last named query in the file.&amp;#160; Your DAL code should take these placeholders as arguments where it needs to. &lt;/p&gt;  &lt;p&gt;Both &lt;em&gt;Java Persistence with Hibernate&lt;/em&gt; and &lt;em&gt;EJB3 in Action&lt;/em&gt; have whole chapters specifically on the JPQL language.&amp;#160; For an online guide try the complete and excellent example provided by BEA at &lt;a href=&quot;http://edocs.bea.com/kodo/docs41/full/html/ejb3_langref.html&quot;&gt;http://edocs.bea.com/kodo/docs41/full/html/ejb3_langref.html&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;External Configuration &lt;/h2&gt;  &lt;p&gt;Any persistence unit should be configurable via external configuration, to prevent us from having to rebuild a persistence unit when it needs to be tweaked to a new database location or new database flavour.&amp;#160; In our example code the file &lt;em&gt;hibernate.cfg.xml&lt;/em&gt; performs this task.&amp;#160; &lt;/p&gt;  &lt;p&gt;When the EntityManagerFactory for a particular Data Access Layer (DAL) is started up, the &lt;em&gt;persistence.xml&lt;/em&gt; refers out to the &lt;em&gt;hibernate.cfg.xml&lt;/em&gt;.&amp;#160; Within our sample application, the following hibernate.cfg.xml content is used: &lt;/p&gt;  &lt;p&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;      &lt;br /&gt;&amp;lt;!DOCTYPE hibernate-configuration PUBLIC       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;&lt;/font&gt;&lt;a href=&quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&quot; ?=&quot;?&quot;&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;hibernate-configuration&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;session-factory&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.show_sql&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.format_sql&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.connection.driver_class&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; org.postgresql.Driver       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.connection.url&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; jdbc:postgresql://localhost:5432/libraries       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&lt;/font&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;&amp;quot;hibernate.connection.username&amp;quot;&amp;gt;postgres&amp;lt;/property&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.connection.password&amp;quot;&amp;gt;&lt;/font&gt;&lt;font face=&quot;Courier New&quot; size=&quot;1&quot;&gt;hello123&amp;lt;/property&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.dialect&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; org.hibernate.dialect.PostgreSQLDialect       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.c3p0.min_size&amp;quot;&amp;gt;5&amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.c3p0.max_size&amp;quot;&amp;gt;20&amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.c3p0.max_statements&amp;quot;&amp;gt;50&amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.c3p0.timeout&amp;quot;&amp;gt;1800&amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.cache.provider_class&amp;quot;&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; org.hibernate.cache.EhCacheProvider       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/property&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;property name=&amp;quot;hibernate.cache.use_query_cache&amp;quot;&amp;gt;true&amp;lt;/property&amp;gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/session-factory&amp;gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/hibernate-configuration&amp;gt; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The &lt;em&gt;show&lt;/em&gt; attribute can be set to false for production systems and true to development systems.&amp;#160; With this set to true, you will see the SQL sent to the database in response to JPA queries and actions at whatever console you have going on the JVM. &lt;/p&gt;  &lt;p&gt;The &lt;em&gt;connection&lt;/em&gt; attributes specify the URL, username, password, and driver to use to connect.&amp;#160; These can be JBoss data source definition, straight-forward JDBC definitions, or HA-JDBC clusters for client side DB HA which we&amp;#8217;ll cover in a future blog. &lt;/p&gt;  &lt;p&gt;The &lt;em&gt;c3p0&lt;/em&gt; attributes are only used for connection pooling outside a JEE container.&amp;#160; When this is configured for JBoss execution, there will not need to be any pool definition here, the pooling will be done within JBoss via its data-source configuration.&amp;#160; However, c3p0 is used by the Hibernate stand alone JPA implementation for out-of-container usage. &lt;/p&gt;  &lt;p&gt;The &lt;em&gt;cache.provider_class&lt;/em&gt; attribute is used to inform Hibernate of a second-level caching implementation at the JVM process level.&amp;#160; This technique is used to stop the JPA implementation from hitting the database unless the data has changed, or is no longer in the second-level cache.     &lt;br /&gt;The &lt;em&gt;cache.use_query_cache&lt;/em&gt; attribute informs Hibernate to turn on named-query caching for any suitably annotated query. &lt;/p&gt;  &lt;p&gt;We&amp;#8217;ll discuss caching as a feature in a follow on blog entry to this one.&lt;/p&gt;  &lt;h1&gt;Conclusions &lt;/h1&gt;  &lt;p&gt;For those of you without an in-depth knowledge of the JPA, we&amp;#8217;re hoping this blog entry has given you enough basic information and confidence to start investigating the JPA for suitability on your projects. &lt;/p&gt;  &lt;p&gt;In the &lt;strong&gt;next blog entry in the series&lt;/strong&gt; we&amp;#8217;ll cover implementing the ideas covered here for out-of-container usage of the JPA, specifying tools, tips, and hopefully pointing you in the right direction. &lt;/p&gt;  &lt;p&gt;In the &lt;strong&gt;final blog on the series&lt;/strong&gt; we&amp;#8217;ll look at caching and database HA with the JPA. &lt;/p&gt;  &lt;p&gt;Jim&lt;/p&gt;  </description><link>http://timepoorprogrammer.blogspot.com/2008/05/how-to-jpa-outside-your-jee-container.html</link><author>noreply@blogger.com (Jim B)</author><thr:total>0</thr:total></item></channel></rss>