Signing commits in Git – How and why

Git is a tool for controlling versions of source code and nowadays of anything as code. This article is intended to help you get started in using the option to sign your commits and tags.

As a reminder I would like to point out that when you clone a git repository, you clone all of the original repository including all commits, tags and changes from the start. Each commit contains meta information like the user name and user email. However, these user names are just set in your own git client configuration:

git config --global "Someone" 
git config --global someone@outthere.zz

When you make changes and create a commit this name and email address will be stored in the git repository. And when you push these changes, this information will be available in the remote repositories as well. So no real proof of who really made the commit.

Authentication of the committer

A first solution to this problem is to use a centrally managed git server. Examples of these are GitHub, Bitbucket, GitLab, and others. All of these managed git servers offer authentication of user access to the repositories as well as other possible restrictions (like rewriting history). All of this extra information is not stored in the git repository itself, but in a datastore used by the managed git server. With this information, you can find out the user id which was used to authenticate with when the commit was pushed. All of these managed git environments use username/password or SSH key based access for authentication.

Is this enough? Do we need signing as well?

The original concept of git was based on a collection of equal git repositories. So in this concept there was a need to be able to trust commits of participants in a repository. Therefore, Git supports signing of commits and tags. And, the signing information is also stored in the Git repositories. The whole concept is based on Pretty Good Privacy, which has a well known implementation of GPG (GnuPG) on Linux, Windows, MacOS, and others. So these signatures in combination with the exchange of the public keys between trusted parties, makes it possible to trust the commit or tag. As these are stored in the repository, you could even move from one managed git server/cloud to another git server/cloud and still have the same trust as it is all contained within the repository.

Example: Signing tag in a CICD pipeline

One use case where signing is also of value even when a managed git server is used, is pushing a signed label as an audit step in a CICD (continuous integration/continuous delivery) pipeline. A tag is a unique label that points to a certain commit which represents the code as it was at that moment in time. Signing the tag means that this label has been used by the owner of the private key and that all others can verify that the label is valid and signed by the expected person. A CICD service account could for instance sign and push this tag as part of the processes of delivering software to production.

Example: GitHub signs commits made from the GUI

Another example is GitHub, which automatically signs commits on behalf of you when you make changes directly from the WEB UI.

Step 1: Install GPG

Before you can do anything with gpg based signatures in git, you must install gpg and configure git to know which gpg program to use:

#e.g. on a Mac you can install gpg using brew
brew install gpg

#now instruct git to use this:
git config --global gpg.program gpg

Now, you can check to see the signature data from the commits, by:

git log --show-signature 

The output on a GitHub based repository could already contain some entries like this:

commit d8c7e72cbed11411b80995d415311c7fb6399d9a
gpg: Signature made do 10 dec 19:23:46 2020 CET
gpg:                using RSA key 4AEE18F83AFDEB23
gpg: Can't check signature: No public key
Author: Someone <git@outthere.zz>
Date:   Thu Dec 10 19:23:46 2020 +0100

Step 2: download the GPG Public key of GitHub

The highlighted key is referring to the id of the public key of the GitHub web-flow agent that automatically signs commits when you are logged in and make commits from the GitHub UI. As you can see, you do not have the public key from the GitHub signer yet. You can get this key and store it in your GPG public keys like this:

curl | gpg --import

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   919  100   919    0     0   3829      0 --:--:-- --:--:-- --:--:--  3829
gpg: key 4AEE18F83AFDEB23: public key "GitHub (web-flow commit signing) <>" imported
gpg: Total number processed: 1
gpg:               imported: 1

Now the result from git log –show-signature will be something like:

commit d8c7e72cbed11411b80995d415311c7fb6399d9a
gpg: Signature made do 10 dec 19:23:46 2020 CET
gpg:                using RSA key 4AEE18F83AFDEB23
gpg: Good signature from "GitHub (web-flow commit signing) <>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 5DE3 E050 9C47 EA3C F04A  42D3 4AEE 18F8 3AFD EB23
Author: René Zubcevic <>
Date:   Thu Dec 10 19:23:46 2020 +0100

Step 3: Trust a public key

You can see that you can now verify the signature, but you still do not have trust in the used public key, and therefore have no trust in the signature [unknown] and no one certified this trust. PGP has a web of trust model which is quite extensive. As you have downloaded the GPG public key from a trusted connection, you can safely trust this public key. This can be done by:

gpg --edit-key
gpg (GnuPG/MacGPG2) 2.2.24; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

pub  rsa2048/4AEE18F83AFDEB23
     created: 2017-08-16  expires: never       usage: SC  
     trust: unknown       validity: unknown
[ unknown] (1). GitHub (web-flow commit signing) <>

gpg> trust
pub  rsa2048/4AEE18F83AFDEB23
     created: 2017-08-16  expires: never       usage: SC  
     trust: unknown       validity: unknown
[ unknown] (1). GitHub (web-flow commit signing) <>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 4

pub  rsa2048/4AEE18F83AFDEB23
     created: 2017-08-16  expires: never       usage: SC  
     trust: full          validity: unknown
[ unknown] (1). GitHub (web-flow commit signing) <>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg> quit

Now [unknown] will have changed to [full] trust, but the message about certification will still be there. In order to get rid of these messages, you have to sign this trusted public key with your own private GPG key which is the process of certification by you. So you also need a private GPG key, which then can be used for signing your own commits in your local repository as well.

Step 4: generate your own private GPG key

gpg --full-generate-key

For GitHub you should choose RSA and a key strength of 4096. Choose no expiry and it is easy to not use a passphrase as long as you are the only one with access to the key. Then the menu will ask for a realm and an email. Make sure that these match the and you use on your GitHub account.

Step 5: Sign the public GitHub key

With this newly generated key, you can sign the GitHub public key:

gpg --lsign-key

Now the git log –show-signature will no longer show warnings about these signatures.

Step 6: Sign your own commits and tags

Now you can sign commits and tags as follows:

gpg --list-secret-keys # get the id of your secret key
git config --global user.signingkey 8503774BDD1AB580AC91CFE69716041EBCCEAFF1 # refer git to this key
git commit -S -m "updated Readme and content"
git tag -s -a v1.0 -m "my v1 version"

Notice that the commit uses a capital S and the tag a lowercase s. If you always want to sign every commit, you can set the config:

git config --global commit.gpgsign true

Step 7: Export and share your public GPG key

Now if you want GitHub to show that your commits can be trusted and if you want GitHub to be used as a means to share your public key, you must extract your public key and enter it in the GitHub section of your profile where you share the public keys.

gpg --armor --export 8503774BDD1AB580AC91CFE69716041EBCCEAFF1

Now upload the output to GitHub. Now anyone, can download and install this public key in the same way we did with the GitHub public key. However, now you will have to use your own GitHub account as part of the url:

#import public key
curl | gpg --import

More information and examples can be found here:

Developer Getting Started Guide for WebGoat

This page is for tips and tricks for developers who want to build WebGoat themselves and think about contributing to WebGoat.

Basic understanding

Development and test of WebGoat can be done on Microsoft Windows, Apple MacOS or a Linux based OS. WebGoat is finally packaged and released as Java jar files and docker containers on Docker Hub. The end result should be runnable on all of the mentioned operating systems.

WebGoat also supports multiple languages. The unit tests and integration tests should be able to handle localisation and user zone settings.

Travis is used to test code that is pushed to GitHub. Everyone with a GitHub account can contribute by creating a fork of WebGoat, then create a branch off of develop in their local repository and making a cross repository pull request. This will trigger the Travis build. Pull requests require that a contributor signs an agreement. Otherwise the pull request can never be merged.


  • Windows, MacOS, Linux operating system
  • Maven 3.5 or higher
  • Java 11 up to Java 13 (which are both tested in the Travis build)
  • An IDE will be handy: e.g. Visual Studio Code, Eclipse or IntelliJ. Make sure that the IDE has the extensions to support Lombok.
  • (optionally) docker (e.g. Docker Desktop for Windows, MacOS)
  • Browser to test manually: Safari, Firefox, Chrome, Edge

Free ports

When you build or run the application with default settings make sure that the following ports are not in use:

  • 8080
  • 9001
  • 9090

Building from Maven

git clone
cd WebGoat
git checkout -b yourbranch
mvn clean install

Default components

The Java build results in two ‘executable’ jar files:

  • WebGoat in webgoat-server/target
  • WebWolf in webwolf/target

Run WebGoat from generated jar

java -jar webgoat-server/target/webgoat-server-v8.2.0-SNAPSHOT.jar

This starts WebGoat with the UI on And an hsql database on port 9001 which has persistent data stored in .webgoat folder.

Run WebWolf from generated jar

java -jar webwolf/target/webwolf-v8.2.0-SNAPSHOT.jar

This starts WebWolf with an UI on whixh is connected to the database on port 9001

First time usage

When you open WebGoat for the first time, you will see the login screen. If you do not have a username and password, then you can use the register function to create a new user. As long as you do not delete the .webgoat folder that username and your results will be present when you use it the next time. Even if you stop and start the application.

Project structure

At the root level there is a overall parent pom.xml which contains all the references to all components of WebGoat and WebWolf. Below this level there are a few main folders:

  • webgoat-container
    • A maven java project that contains the core or framework of the WebGoat application
    • is the main property file used for Spring Boot
  • webgoat-lessons
    • Folder that contains a lot of sub maven project folders, where each folder is a lesson on its own
  • webgoat-server
    • Contains the Spring Boot application for WebGoat
    • is the main class
  • webwolf
    • Contains the Spring Boot application for WebWolf
    • is the main class
    • is the main property file for Spring Boot
  • webgoat-integration-tests

Building your own WebGoat lesson

WebGoat comes with an built-in lesson on how to build your own WebGoat lesson. Make sure you first complete this exercise before you try to add a new lesson.

Kickstart your application before adding full load

A common challenge for most application is the response time of the initial incoming requests. The initial requests trigger a lot of initialization code caused by opening connections and setting up connection pools as well as instantiating objects for singletons etc.

If your application is response time critical, you need something extra to prevent that these initializations effect your client request and related service level agreements. E.g. 1 initial response of 30 seconds could cause a timeout exception in your clients and will have a devastating effect on your SLA if you have to realize an average response of say 50 ms.

This article will describe some ways to kickstart your application in a way that the real client application requests will be handled fast from the start.

Manage the incoming load

Make sure that when you add an application instance, the load is slowly increased on the new instance when it is marked available.

In case you have or want to restart your application for an application upgrade or other reason, you have to:

  •  Mark the instance as unavailable and wait for all existing connections to be closed.
    • Usually the existing http(s) connections will remain used until the socket is closed. (In apache http e.g. based on MaxKeepAliveRequests and KeepAliveTimeout
  • Then do your maintenance or upgrade followed by a health check and/or canary test and the kickstart requests as mentioned in the next section
  • Then mark the instance as available and allow incoming requests to the new instance (in a controlled way)

Kickstart the application with near-to-real requests

Suppose you are able to send in real requests, then everything gets initiated perfectly. But suppose you build a payment system and you insert payments, then these payments will get processed or rejected, but it will be undesirable that such payments are done. So a near-to-real request which triggers almost the same execution path is a better solution.

A solution can consist of the following elements:

  1. Extra code in the application to support and secure this
  2. Bash scripts to send kickstart requests
  3. Extra configuration in HTTP Server, Linux to allow requests in a limited and secured way

1a Code that executes at startup before the application becomes available

In Java EE or Spring you can define code that automatically starts when the application is started. This is a perfect place to do some basic initializations that benefit the whole application:

  • Do some database queries to open up connections to the database
  • Do some database queries on configuration data to fill up caches
  • Call some backend services to open up http(s) connections, MQ connections or other resource related connections
  • Initialize (hardware) keystores and do some singing or validation

However this will not really initialize your own SOAP and REST service end points.

1b Code that detects kickstart requests and stops the request just-in-time

A near-to-real request must have some elements that can be detected so these will be treated in the right way. Basic steps include:

  • Detect the origin
  • Detect normal kickstart request or attempt to misuse the kickstart functionality (fraud)
  • Change the request in a way that the end result is not the same as a real request. E.g. a kickstart request does a lot of steps but in the end it will be rejected and not stored or logged as incidents.

2 Bash or other tools that send kickstart request

You need something that sends out a kickstart request and that something is only to be executed within the same instance of the application by the something that automatically starts the application.

3 Special configuration in the middleware/infrastructure

You need some protective measures such that the kickstart cannot be accessed outside of the instance itself.

Results of implementing such kickstart requests

The results of implementing such a solution (I cannot share to much details) is really worth the while.

The initial request in my case was 19 seconds, and all subsequent requests were under 100 ms. Where you still could see that some code paths for the real request were still new, but the greatest reduction in response times were already realized.




Deployment automation in XL Deploy

Deployment automation in XL Deploy is great, but do not forget to automate the setup and configuration of your XL Deploy environment as well.

Try to avoid using the user interface and try to avoid adding entries to the dictionaries manually. In stead use the API to create all of your infrastructure, environments, and dictionaries. Treat the set up of XL Deploy as code!

Here is a link to their API: XL Deploy Rest API
And here is some example of how you could use it in a bash script.

# Helper methods for accessing XLDEPLOY API using CURL
del_ci() {

curl -H "Authorization: Basic $XLD_BASICAUTH" -k -X DELETE -H "Content-type:application/xml" $XLD_SERVER/deployit/repository/ci/$1 --data "<$2 id=\"$1\"></$2>"


add_ci() {

curl -H "Authorization: Basic $XLD_BASICAUTH" -k -X POST -H "Content-type:application/xml" $XLD_SERVER/deployit/repository/ci/$1 --data "<$2 id=\"$1\">$3</$2>"


update_ci() {

curl -H "Authorization: Basic $XLD_BASICAUTH" -k -X PUT -H "Content-type:application/xml" $XLD_SERVER/deployit/repository/ci/$1 --data "<$2 id=\"$1\">$3</$2>"


add_ci_from_file() {

curl -H "Authorization: Basic $XLD_BASICAUTH" -k -X POST -H "Content-type:application/xml" $XLD_SERVER/deployit/repository/ci/$1 -d@$2


add_ci Environments/test core.Directory
add_ci Environments/test/test_dict udm.Dictionary "<entries>
    <entry key=\"DATABASE_URL\">$dep_DATABASE_URL</entry>
  	<entry key=\"DB_PASSWD\">$db_password</entry>

Keeping track of the dictionary keys in combination with the keys being used in certain versions of your deployable archives is very important in order to realize reliable and more consistent results.

In the end these kind of deployment robots like XL Deploy or Nolio will have to become more and more mature in supporting immutable server concepts so that code and configuration is exactly the same in all environments.

Continue reading

Porting the app to the MEAN stack

So far the reference application has been built on the Java EE stack for Java EE runtime environments. However, the same application can be build in other programming languages as well.

The MEAN stack consists of MongoDB, Express, AngularJS, and Node JS. Node JS is the main programming platform differentiator.

Porting the reference application consists of two parts: 1) Moving the static UI html and javascript Angular parts to NodeJS, and 2) Re-implementing the REST calls and servlet calls that are used in the controllers.

Part 1 is very easy as the original application was allready based on AngularJS. However there was one issue that needed to be resolved. By default the mongoose framework uses the property names of the documents in MongoDB as properties in the returned JSON objects in the REST API.

This is not always a desired feature. It can be resolved by either changing the AngularJS controller or by using a NodeJS framework that enables aliasing properties in mapping documents to objects.

Porting part 2 will depend on what kind of functionality and functions are used in the business and persistency layers. Implementing the CRUD functions on a MongoDB database using the mongoose and express modules of Node JS is straightforward. The only thing that you need to worry about on Bluemix is that you need to process the database connection details of your service which are available through parsing the VCAP_SERVICES environment variables. This JSON object contains information about the database connection and other services.

var mongoose = require('mongoose');
mongoose.set('debug', true)
var db;
if (process.env.VCAP_SERVICES) {
	   var env = JSON.parse(process.env.VCAP_SERVICES);
	   db = mongoose.createConnection(env['mongolab'][0].credentials.uri);
	} else {
		console.log("creating connection");
		db = mongoose.connect('mongodb://taxreturn:taxreturn@localhost:27017/taxreturns');

Now the Bluemix environment with a Java EE and a NodeJS application using the same MongoLab MongoDB instance looks like:Bluemix topology

Building a MongoDB topology using MMS automation

As mentioned in previous blogs the reference application can use MongoDB.
For this a MongoDB database needs to be set up. You can do this in any number of ways:

  1. Download the software on your server, start the mongod process and configure your application with the connection details
  2. Get MongoDB as a SaaS service from MongoLab or other providers, followed by the same steps

If you decide to build your own database, you can do so by configuring everything manually or using scripts, however you can also choose to use MMS as a kind of SaaS solution for managing your MongoDB environment. This can be done on private clouds/networks using your own dedicated MMS solution, or in the public cloud.

The picture below shows such an environment:
MongoDB topology

Using MMS to set up this complex topology is quite simple:

  1. Start by installing the automation agents. These will then connect to the environment using some shared secrets that have been configured for your account. This will make these agents appear on your account.
  2. Then use the web interface of MMS to install monitor agents and/or backup agents and everything else that you need: standalone servers, sharded clusters etc.

The automation agents will automate all the deployment and installation tasks needed, such as:

  • downloading software of the desired version
  • upgrading versions of the agents and databases
  • configuring security
  • creating & changing clusters

Without MMS, I would have needed much more time to set up such a cluster. The alternative is to go SaaS all the way, where you don’t care anymore about how and where it is installed. In that case MongoLab solutions or the MongoLab within Bluemix solution is a good choice as well.

For now I think that using MMS in combination with your own infrastructure is a very good choice. And using a private MMS would be even better from a security and trust/privacy point of view.

Application landscape in the Bluemix cloud

The reference application that I am building is a Java EE application that runs on JBoss, WebSphere Liberty, WebSphere Full and can be run on local Windows or Mac laptops, on Raspberry Pi, in docker or on the IBM Bluemix cloud.

The picture below shows the landscape of the reference application in the Bluemix cloud.

Bluemix topology

In Bluemix you can choose in which region you want to host your application. E.g. UK or US South. Within each region you then have the opportunity to define spaces, such as dev, test, prod. Each space then consists of your application and bounded services.

Also Bluemix provides the opportunity to deploy your application in multiple ways: As a CloudFoundry app, as a docker container or as a virtual machine.

The reference application is deployed as a cloudfoundry app on a WebSphere Liberty instance. It is bounded to several services: The single sign on service, a MongoDB service from MongoLab, a MySQL service from ClearDB.

Currently, not all services are available in each region. This depends on the overall state of such a service. The Single Sign On service which offers OAUTH or OpenID integration was initially only available in the US South region. This service can be used to provide authentication functionality to your application. Your application then needs to provide autorisation based on the user id from the authentication system.

The reference application is aware of the authentication system. That is, it knows whether standard Java EE authentication with LDAP user registries in the Java EE container are being used or OAUTH is used.

All information of the services are available in CloudFoundry based environment variables as well as being defined as Java EE resources (MySQL datasource and MongoDB liberty database connection pool) in the liberty server configuration.

The code of the application can be deployed locally from Eclipse or other development tool, or from a build pipeline configured in the DevOpsServices environment. This environment is fully integrated with Bluemix, GIT and other tools and can be configured in such a way that an application will be automatically build, and deployed to one or more environments in Bluemix.

Content Security Policy, browsers and angularJS

In order to protect your application on the client side, content security filtering (CSP) has been introduced. It is basically an HTTP Header added by your web application to instruct a browser to handle content in a certain secure way.

Unfortunately, as it is dependent on the browser technology, not all browsers support CSP and not all browsers act on the same HTTP Header. However, for most recent browsers you can improve your overall security by introducing CSP. Older browsers will not use this additional safety.

With CSP enabled, you can instruct the browser to only allow JavaScript from trusted and file based resources. Disallowing inline JavaScript. The same applies for stylesheets and in-line styles.

You can enable CSP fully or in reporting mode. Fully means that the browser will block all non-allowed elements. In reporting mode, means that the browser will send reports back to the server of all things that are not allowed. These reports are posted in to a REST service hosted by your application. This is a nice way for developers to test their application and see whether or not everything works fine with CSP enabled.

Enabling CSP & AngularJS

Enabling CSP has impact on the frameworks you are using. Suppose you are using AngularJS and/or BootStrap. Then you might need to set up things a bit different.

In AngularJS 1.3.9 you need to include a stylesheet angular-csp.css seperately. Also, you should add ng-csp as an attribute in your html tag.

Then start debugging in your browser to see what goes wrong and should be changed in your application to make it more safe.

HTTP Headers

The HTTP Headers you should provide are at least the following:

  • Content-Security-Policy
  • X-Content-Security
  • Content-Security-Policy
  • X-WebKit-CSP

The values can be the same for each header, but this will cover most browsers. -Report-Only can be added in reporting mode.

More info

For more info see the official web sites on CSP and check out sample implementations on OWASP.

You should start using CSP early in your project development. Because it will be hard to fix all non compliant issues later on.

Managed webservice clients

One of the application server specific things is the use of managed web service clients. Especially since you will always want to configure the location of your service endpoints.

WebSphere Liberty and WebSphere Regular also do this their own way.

Let’s start with development of a managed web service client. Start with a wsdl and generate the client code. Then use @WebServiceRef to link your servlet or ejb code to the service client.

@DeclareRoles({ "BANKADMIN", "BANKUSER" })
public class ExpenseService {

	@WebServiceRef(name = "ws_PaymentWebService", value = PaymentWebService.class)
	private PaymentInterface service;

When you do not provide any more information, the endpoint address is determined from the wsdl that is accessible for the client.

You can override this for WebSphere with the use of the ibm-webservicesclient-bnd.xmi file, and for WebSphere Liberty using the ibm-ws-bnd.xml

ibm-webservicesclient-bnd.xmi for WebSphere Application Server

<?xml version="1.0" encoding="UTF-8"?>
< xmi:version="2.0" xmlns:xmi="""" xmi:id="ClientBinding_1427118946547">

  <serviceRefs xmi:id="ServiceRef_1427119116658" serviceRefLink="ws_PaymentWebService">
    <portQnameBindings xmi:id="PortQnameBinding_1427119116658" portQnameNamespaceLink="" portQnameLocalNameLink="PaymentWebServicePort" overriddenEndpointURI="https://localhost:9443/accountservice/PaymentWebService"/>


Once you have added this binding file, you can add instructions during the deployment process to override the actual timeout and endpoint values for a particular environment. This is done using additional install parameters in Jython/wsadmin or e.g. in XLDeploy:

<was.War name="accountservice" groupId="com.zubcevic.accounting"
      <value>-WebServicesClientBindPortInfo [['.*'  '.*' '.*'  '.*' 30 '' '' '' 'https://myserver1/accountservice/PaymentWebService']]</value>

ibm-ws-bnd.xml for WebSphere Liberty

<?xml version="1.0" encoding="UTF-8"?>
<webservices-bnd xmlns=""
	<service-ref name="ws_PaymentWebService" wsdl-location="WEB-INF/wsdl/PaymentWebService.wsdl">
		<port name="PaymentWebServicePort" namespace=""
				address="https://localhost:9443/accountservice/PaymentWebService" username="admin" password="password"/>


Some may say, that you could make things more easy by doing it yourself (unmanaged service client) and reading some endpoint configuration from a property file. But it will get more and more difficult when you want to additional configuration like SSL transport security settings, basic authentication, WS Addressing, WS Security and others.
With managed clients you can have this stuff get arranged by the application server. In stead of building your own application server capabilities in your application.

Flexible persistency – SQL or NoSQL

The reference application that I am building, supports both relational database or document database persistency.

The object model of my application consists of classes that are used in both. A factory determines dynamically whether to use a SQL or a NO-SQL database.  Or to be more precise, MySQL or MongoDB.

Java EE JPA is used to make it fit almost any SQL database, while MongoDB specific API is used to operate on MongoDB. Alltough JPA stands for Java Persistency API and is therefore not necessarily related to SQL databases, the use of specific annotations more or less assume that SQL databases are used.

In my application the domain objects do have JPA annotations and are used by an entity manager for persistence in MySQL and a bespoke document manager for MongoDB. All implementing the same interface.

The interface looks like:

public interface BankAccountManager {

	public List<BankAccount> getBankAccounts(User user);
	public List<MoneyTransfer> getMutations(BankAccount bank);
	public void storeMutations(BankAccount bAccount,List<MoneyTransfer> transfers);

The factory for getting the right implementation looks like:

public class BankAccountManagerFactory {

    private BankAccountManager docManager;
    private BankAccountManager entityManager;
	private BankAccountManager expManager;
	private boolean isDoc = false;      
	public void initEM() {
		if (isDoc) {
			expManager = docManager;
		} else {
			expManager = entityManager;
	public BankAccountManager getBankAccountManager() {
		return expManager;

In this example, the choice for using one or the other is hardcoded, but merely used as an example that you can switch based on something in your code path. The names of the EJB’s will be matched to the correct implementations of the EJB’s for this same interface. The names must be specified otherwise the correct implementation cannot be determined by your container.

A sample class that uses the BankAccountManager then looks like:

public class UploadSwift extends HttpServlet {
	private static final long serialVersionUID = 1L;
	@EJB private BankAccountManagerFactory bankAccountManager;

So in my application I could have chosen to use @EJB(beanName=”BankAccountEntityManager”) in my servlet, but that would make it really hardcoded. Using the factory I can determine it by some other rule. It’s still a hardcoded boolean at the moment, but could also be an environment variable or such thing.

In a future post, I will explain more about the differences in schema design and differences between relational and document oriented data.