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 mms.mongodb.com 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.

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:

@Local
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:

@Singleton
public class BankAccountManagerFactory {

	@EJB(beanName="BankAccountDocumentManager")
    private BankAccountManager docManager;
    
	@EJB(beanName="BankAccountEntityManager")
    private BankAccountManager entityManager;
    
	private BankAccountManager expManager;
	
	private boolean isDoc = false;      
	
	@PostConstruct
	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:

@WebServlet("/upload")
@MultipartConfig
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.