Deploying a JHipster/MongoDB application to Heroku

1.3k views Asked by At

JHipster offers sub-generators for deploying applications to cloud providers (such as Heroku and Openshift), but not for applications using MongoDB due to the fact that Mongeez requires admin privileges which of course is not possible within a PaaS environment.

However, it should be possible to run JHipster + MongoDB on cloud providers as long as Mongeez is deactivated. I did the following (using Heroku):

  • First, I manually exported the MongoDB database that was created by JHipster on my local development machine and imported it on a Mongolab instance.
  • In case the used profile is prod, Mongeez doesn't get instantiated.
  • After some modifications to JHipster's Heroku subgenerator, it was possible to deploy the app to Heroku. The generator now ignores _HerokuDatabaseConfiguration.java (which is for JDBC) and in the used Procfile, I changed the profile to prod (instead of prod,heroku) and removed the parameter --spring.datasource.heroku-url=$DATABASE_URL.

It works quite well, but I have problems with injecting the MongoDB connection string. At the moment, the credentials are "hardcoded" into application-prod.yml, so it would be necessary to redeploy the whole application in case of a change of the credentials. In another attempt, I added spring.data.mongodb.uri=$MONGOLAB_URI to the Procfile, but there wasn't any effect (unless I missed something).

So how could I solve this issue? As I said, the application is running on Heroku without any problems, but it would be nice to derive the connection details from e.g. the MONGOLAB_URI environment variable. In other news, I have a feeling that I don't understand the cloud profile (which I do not use at the moment).

1

There are 1 answers

0
Matyas On

Instead of Mongeez you can use mongobee to provide the migration logic for your app.

I've tried it and it works on heroku.

This is my default mongobee migration code for jhipster that has the same effect as the mongeez one.

package your.package.name.config.dbmigrations;

import com.github.mongobee.changeset.ChangeLog;
import com.github.mongobee.changeset.ChangeSet;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Creates the initial database setup
 */
@ChangeLog(order = "001")
public class InitialSetupMigration {


    private Map<String, String>[] authoritiesUser = new Map[]{new HashMap<>()};

    private Map<String, String>[] authoritiesAdminAndUser = new Map[]{new HashMap<>(), new HashMap<>()};

    {
        authoritiesUser[0].put("_id", "ROLE_USER");

        authoritiesAdminAndUser[0].put("_id", "ROLE_USER");
        authoritiesAdminAndUser[1].put("_id", "ROLE_ADMIN");
    }

    @ChangeSet(order = "01", author = "initiator", id = "01-addAuthorities")
    public void addAuthorities(DB db) {
        DBCollection authorityCollection = db.getCollection("jhi_authority");
        authorityCollection.insert(
            BasicDBObjectBuilder.start()
                .add("_id", "ROLE_ADMIN")
                .get());
        authorityCollection.insert(
            BasicDBObjectBuilder.start()
                .add("_id", "ROLE_USER")
                .get());
    }


    @ChangeSet(order = "02", author = "initiator", id = "02-addUsers")
    public void addUsers(DB db) {
        DBCollection usersCollection = db.getCollection("jhi_user");
        usersCollection.createIndex("login");
        usersCollection.createIndex("email");
        usersCollection.insert(BasicDBObjectBuilder.start()
            .add("_id", "user-0")
            .add("login", "system")
            .add("password", "$2a$10$mE.qmcV0mFU5NcKh73TZx.z4ueI/.bDWbj0T1BYyqP481kGGarKLG")
            .add("first_name", "")
            .add("last_name", "System")
            .add("email", "system@localhost")
            .add("activated", "true")
            .add("lang_key", "en")
            .add("created_by", "system")
            .add("created_date", new Date())
            .add("authorities", authoritiesAdminAndUser)
            .get()
        );
        usersCollection.insert(BasicDBObjectBuilder.start()
            .add("_id", "user-1")
            .add("login", "anonymousUser")
            .add("password", "$2a$10$j8S5d7Sr7.8VTOYNviDPOeWX8KcYILUVJBsYV83Y5NtECayypx9lO")
            .add("first_name", "Anonymous")
            .add("last_name", "User")
            .add("email", "anonymous@localhost")
            .add("activated", "true")
            .add("lang_key", "en")
            .add("created_by", "system")
            .add("created_date", new Date())
            .add("authorities", new Map[]{})
            .get()
        );
        usersCollection.insert(BasicDBObjectBuilder.start()
            .add("_id", "user-2")
            .add("login", "admin")
            .add("password", "$2a$10$gSAhZrxMllrbgj/kkK9UceBPpChGWJA7SYIb1Mqo.n5aNLq1/oRrC")
            .add("first_name", "admin")
            .add("last_name", "Administrator")
            .add("email", "admin@localhost")
            .add("activated", "true")
            .add("lang_key", "en")
            .add("created_by", "system")
            .add("created_date", new Date())
            .add("authorities", authoritiesAdminAndUser)
            .get()
        );
        usersCollection.insert(BasicDBObjectBuilder.start()
            .add("_id", "user-3")
            .add("login", "user")
            .add("password", "$2a$10$VEjxo0jq2YG9Rbk2HmX9S.k1uZBGYUHdUcid3g/vfiEl7lwWgOH/K")
            .add("first_name", "")
            .add("last_name", "User")
            .add("email", "user@localhost")
            .add("activated", "true")
            .add("lang_key", "en")
            .add("created_by", "system")
            .add("created_date", new Date())
            .add("authorities", authoritiesUser)
            .get()
        );
    }

    @ChangeSet(author = "initiator", id = "03-addSocialUserConnection", order = "03")
    public void addSocialUserConnection(DB db) {
        DBCollection socialUserConnectionCollection = db.getCollection("jhi_social_user_connection");
        socialUserConnectionCollection.createIndex(BasicDBObjectBuilder
                .start("user_id", 1)
                .add("provider_id", 1)
                .add("provider_user_id", 1)
                .get(),
            "user-prov-provusr-idx", true);
    }
}

In the DatabaseConfiguration.java file remove mongeez and add

@Bean
public Mongobee mongobee() {

    log.debug("Configuring Mongobee");

    Mongobee mongobee = new Mongobee(mongo);
    mongobee.setDbName(mongoProperties.getDatabase());
    mongobee.setChangeLogsScanPackage(
        "de.shaere.sharecore.config.dbmigrations"); // package to scan for changesets
    mongobee.setEnabled(true);
    return mongobee;
}

And finally update your gradle file removing the mongeez dependency and adding:

compile group: 'com.github.mongobee', name: 'mongobee', version: mongobee_version

I've also opened a pull request to update the JHipster generator. Now we wait to see if the guys agree :)