Documentation Home

Site Provisioning

Most implementations of the MultiTenant module will need to automate the creation of new sites. This process is likely
to be highly specific to your needs.

Broadleaf Commerce uses the MultiTenant module for our private demo environment. As such, we have an approach and some
components that you may be able to leverage with your implementation.

This section describes the key considerations that our private demo uses and some pointers to how we do it.

Requesting a new Site

From our main website, customers are able to request a Private Demo. Our business logic is that if you give us a
valid email and agree to terms then you can have private demo site. Your business logic is likely more difficult.

Nonetheless, we store the email address of the requesting individual, create a random token (representing the domain prefix
for the site), and send the user an email letting them know that their demo site is available.

Creating the Site

Regardless of how you choose to create a new site, the first step is setting up data for the site.

A good place to start for this is the createSite method in MultiTenantService.

Here is the default implementation of this method found in MultiTenantServiceImpl.java ...

/**
 * Creates a site, initial admin user for the site, and 
 * @param siteDto - object providing information on how the site will be resolved and the initial admin user.
 */    
public SiteResponse createSite(final SiteDto siteDto) {
    SiteResponse siteResponse = new SiteResponse();
    GenericResponse response = new GenericResponse();
    siteResponse.setGenericResponse(response);

    final String identifier;
    if (!StringUtils.isEmpty(siteDto.getDomainPrefix())) {
        identifier = siteDto.getDomainPrefix();
        if (identifier.contains(".") || !identifier.matches(validDomainPrefixRegex)) {
            response.addErrorCode("invalidDomainPrefix");
        }
    } else if (!StringUtils.isEmpty(siteDto.getDomainName())) {
        identifier = siteDto.getDomainName();
        if (!identifier.matches(validDomainRegex)) {
            response.addErrorCode("invalidDomainName");
        }
    } else {
        response.addErrorCode("domainPrefixOrNameRequired");
    }

    if (StringUtils.isEmpty(siteDto.getPassword())) {
        response.addErrorCode("passwordRequired");
    } else if (StringUtils.isEmpty(siteDto.getConfirmPassword())) {
        response.addErrorCode("confirmPasswordRequired");
    } else if (!siteDto.getPassword().equals(siteDto.getConfirmPassword())) {
        response.addErrorCode("passwordConfirmMismatch");
    }

    // Ensure that this operation is being called by a user with global admin permissions
    AdminUser globalUser = adminUserDao.readGlobalAdminUserByUserName(siteDto.getUsername());
    if (globalUser != null) {
        response.addErrorCode("invalidUsername");
    }

    if (!response.getHasErrors()) {
        // Work to actually create the site in the DB
        final Site site = siteProvider.createSite(siteDto);

        // Create the roles
        createDefaultAdminRoles(site);

        // Create the site admin
        createSiteAdminUser(siteDto, site);

        // Logic allowing extension by other modules (mainly the theme module which needs to react to the
        // new site by creating a new ThemeConfiguration instance for the site).
        for (final SiteConfigProvider siteConfigProvider : siteConfigProviders) {
            IdentityExecutionUtils.runOperationByIdentifier(new IdentityOperation<Void, RuntimeException>() {
                @Override
                public Void execute() {
                    siteConfigProvider.configSite(site);
                    return null;
                }
            }, site);
        }
        siteResponse.setSite(site);
    }
    return siteResponse;
}

Reviewing the code above will give you a good idea of the key mechanics for automating the provisioning of a site.
The code above can be used as is for many implementations. One special note is the siteProvider.createSite.

The SiteProvider interface is implemented by the component blSiteProvider. The out of box implementation is bare
bones and simply creates the Site record in the database. This component can be extended to also perform data
setup routines when provisioning the site.

At Broadleaf, we use the out of box createSite method to create the site and then immediately follow that with a call
to a class that creates the sample data needed for the application.