Skip to Content
Author's profile photo Matthias Steiner

Enterprise Granny Part 2: Making it run

Open Source for the win

One of the best aspects of Open Source software is that it is easy to use! You can freely download the software and usually there is a great documentation and sample coding that comes along with it, resulting in a very low entry barrier. Furthermore, usually the code quality of popular project is really good and sets the gold standard to strive for. These two factors lead the way to mass adoption, which further improves the quality of code as any bugs that there may are are usually discovered and fixed. Last, but not least – this mass adoption results in steadily growing communities experienced with these open source projects and usually these communities are freely sharing their expertise answering questions on social forums like stackoverflow. These are the reasons that drove us to start sharing samples, tools and frameworks as Outbound Open Source projects ongithub.

As mentioned in part 1 of this series we have forked a very simple demo application called “Granny’s Addressbook” and want to make it more enterprise-ready throughout the course of the next weeks. We’ll share our approach and considerations in accompanying blogs, yet as a software developer there’s only a single point of truth – the source code!

Let’s get started

So, before we start about enhancing the application we first need to obtain it and then make it run! Once we accomplished this we can have a closer look, analyze the architecture of the application and then start to make it better. But we said we take it step-by-step and hence let’s focus on making the application as-is first.

“Enterprise Granny” is a Maven-based application and the source code is available on github here: https://github.com/SAP/cloud-enterprise-granny

Those that have never worked with Git and Maven before, may want to check-out this tutorial I wrote a while ago, which walks you through the process of installing the necessary tools. With that knowledge you should be able to clone the github repo (repository) and import it into your local Eclipse IDE.

[Ref] Essentials – Working with Git & Maven in Eclipse

Making it run

If you browse the commit history of the project to see the first changes I applied after forking it you’ll notice mainly two changes called ‘meta’ and ‘DB abstraction‘. Now, the first was mainly about getting rid of some old artefacts (Eclipse specific configuration files) and some meta-information. Much more interesting is the changes I applied to make the application DB-agnostic. The original “Granny application” used HSQL or PostgreSQL as the underlying DB [Ref]. The first is merely a in-memory database (which does not store data permanently) and the second isn’t available in the SAP HANA Cloud Platform.

Even more important, we don’t want to tie our application to a particular database anyway as this would limit us to a specific environment. Instead we want to leverages a concept called “DB as a Service”, which allows us to use standard APIs to interact with a default datasource that is automaticallyprovisioned by the platform at runtime. This comes in handy during the development of the application as we can deploy it locally and to the cloud without having to apply any changes to the configuration. Let’s have a closer look at how this is accomplished…

Making Granny DB-agnostic

So, let’s have a closer look at the changes I applied (here’s the corresponding commit log). The following five files have been changed:

Let’s go through them one by one:

pom.xml

When talking to people that are not too familiar with Maven I usually describe it as sort of a recipe (as in cooking). In a nutshell it lists all the required dependencies (ingredients) and the build instructions (how to cook). In this file I basically removed all the dependencies we no longer need (HSQL, PostgreSQL and Hibernate) and replace them with the required EclipseLink dependencies. I also added a dependency to Derby, which is the DB I use locally. (For more information on how-to use Derby as your local DB, please see this blog: Essentials – Working with the local database).

Address object

While trying to make the project run locally I ended up with some strange SQL errors. At a closer look I realized that they were caused by the leading underscore used by the ID field in the Address object. Some databases may be able to handle it, but not Derby (see here), and for the sake of portability I decided to make a minimally invasive change by introducing a single @Column annotation, which makes sure that the column name in the DB is always just “ID”. This change has no impact on the application though.

persistence.xml

All that was needed to be done here is to replace the JPA Provider from Hibernate to EclispeLink.

app-context.xml

Again, I mostly changed the JPA related configuration from Hibernate to Eclipse. The most important change to notice is the way I declared the DataSource though:

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/DefaultDB" />

Hereby, we get rid of the hard-coded JDBC configuration to obtain a reference to the DataSource, but instead declare that it is provided by the runtime container via a standard JNDI lookup with the provided name. So, how does that work? How hoes the DataSource become accessible via JNDI?

web.xml

Well, the answer is simple and brings us to the last change applied in the web.xml file. Here, we declare a so called resource reference to the DataSource. The rest if taken care of by the platform runtime. As stated in the documentation:

The persistence service binds the default data source that maps to your Web application’s database schema as a resource to Tomcat’s JNDI (Java Naming and Directory Interface) registry. Before you can consume the data source in your Web application, you need to declare a reference to the default data source provided by the persistence service.

Wrap-up

That’s it: the application is now ready to run on both your local server as well as in the cloud. Before we start applying further changes to make the application more enterprise-ready it may make sense to have a closer look at its architecture in order to get a better understanding of the pain points. So, in the next part of this series we’ll do exactly that and discuss the good, the bad and the ugly. Stay tuned…

PS: If you should have any further questions related to the changes discussed here, please feel encouraged to do so! 😉

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Chris Paine
      Chris Paine

      Hi Matthias,

      Thanks for taking the time to explain this in a very detailed manner for some changes which probably took you only a few minutes. It is an exceptionally readable blog series.

      I wonder if it might be worth providing a few links to explain how using the Java Persistence API provides such an easy way of building your db access model - especially for those used to coding their own DAO and having so much fun with writing different SQL for Derby, MaxDB and if they're lucky HANA.

      Thanks,

      Chris

      Author's profile photo Matthias Steiner
      Matthias Steiner
      Blog Post Author

      Hi Chris,

      happy you find this series worthwhile.

      Actually, your comment needs a SPOILER tag as I wanted to get into this topic down the road. As a teaser I can say that EclipseLink as a JPA provider does a great deal of simplifying the DB access layer. But the really neat features in the sample app are provided by a framework called Spring Data which eliminates the tedious job of writing CRUD managers. Have a look at the AdressRepository interface... that's all that it takes, the rest (e.g. the implementation of this interface = there's none!) is all handled by Spring for you. I'll explain that in more details as we move along... after all, I promised to take it easy at first 😉

      Cheers,

      Matthias

      Author's profile photo Chris Paine
      Chris Paine

      I look forward to the next instalment! 🙂 Whilst I read a little more on Spring Data!

      Author's profile photo Former Member
      Former Member

      Matthias,

      First of allThanks for your contribution!

      I have already installed and Run the Granny Db-Agnostic on my trial, it workes great!

      Can someone explain to me Where are the Generates tables in my HANA Trial? I saw that there is a derby Db when run locally, then I traced the log of my app in hana and I saw the CRETAE statement of the table etc.

      Then I run again the App and the inserted data in granny are still there. So I learned that JNDI will select the datasource at runtime:

      web.xml

        <resource-ref>

          <res-ref-name>jdbc/DefaultDB</res-ref-name>

          <res-type>javax.sql.DataSource</res-type>

        </resource-ref>

      My Hana Binding is this:

      /wp-content/uploads/2016/04/binding_937642.png

      Thanks!!

      These are partis of my log:

      2016 04 22 22:28:41#INFO#LJS_OUTPUT#Thread-11#[EL Info]: 2016-04-22 22:28:41.642--ServerSession(109984440)--Thread(Thread[localhost-startStop-1,5,main])--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11#[EL Fine]: connection: 2016-04-22 22:28:42.285--Thread(Thread[localhost-startStop-1,5,main])--Detected database platform: org.eclipse.persistence.platform.database.HANAPlatform|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11#[EL Config]: connection: 2016-04-22 22:28:42.338--ServerSession(109984440)--Connection(284411229)--Thread(Thread[localhost-startStop-1,5,main])--connecting(DatabaseLogin(|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11# platform=>HANAPlatform|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11# user name=> ""|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11# connector=>JNDIConnector datasource name=>null|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11#))|

      other part:

      Connected: jdbc:sap://vadbj14.nwtrial.od.sap.biz:30015|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11# User: NEO_F3ZGFYKPZZLJ7EPFSJPQTBRWE|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11# Database: HDB Version: 1.00.97.03.1443520413|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11# Driver: HDB Version: 1.96.00-24de221c9810b5c802f2c50962c535d8a9018577|

      2016 04 22 22:28:42#INFO#LJS_OUTPUT#Thread-11#[EL Info]: connection: 2016-04-22 22:28:42.717--ServerSession(109984440)--Thread(Thread[localhost-startStop-1,5,main])--file:/usr/sap/ljs/webapps/cloud-granny/WEB-INF/classes/_application login successful|

      2016 04 22 22:28:43#INFO#LJS_OUTPUT#Thread-11#[EL Fine]: sql: 2016-04-22 22:28:43.073--ServerSession(109984440)--Connection(49489469)--Thread(Thread[localhost-startStop-1,5,main])--CREATE TABLE ADDRESS (ID BIGINT NOT NULL, ADDRESS NVARCHAR(255), EMAIL NVARCHAR(255), NAME NVARCHAR(255), PHONE NVARCHAR(255), PRIMARY KEY (ID))|

      2016 04 22 22:28:43#INFO#LJS_OUTPUT#Thread-11#[EL Fine]: sql: 2016-04-22 22:28:43.12--ServerSession(109984440)--Connection(1811039590)--Thread(Thread[localhost-startStop-1,5,main])--CREATE TABLE SEQUENCE (SEQ_NAME NVARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(34), PRIMARY KEY (SEQ_NAME))|

      2016 04 22 22:28:43#INFO#LJS_OUTPUT#Thread-11#[EL Fine]: sql: 2016-04-22 22:28:43.141--ServerSession(109984440)--Connection(2130328952)--Thread(Thread[localhost-startStop-1,5,main])--SELECT * FROM SEQUENCE WHERE SEQ_NAME = SEQ_GEN|