Java tutorial
/* * Copyright 2015 herd contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.finra.herd.service.impl; import static org.finra.herd.model.dto.SearchIndexUpdateDto.SEARCH_INDEX_UPDATE_TYPE_CREATE; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.BooleanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import org.finra.herd.core.helper.ConfigurationHelper; import org.finra.herd.dao.BusinessObjectDataDao; import org.finra.herd.dao.BusinessObjectDefinitionDao; import org.finra.herd.dao.BusinessObjectFormatDao; import org.finra.herd.dao.config.DaoSpringModuleConfig; import org.finra.herd.dao.exception.CredStashGetCredentialFailedException; import org.finra.herd.dao.helper.CredStashHelper; import org.finra.herd.dao.helper.JsonHelper; import org.finra.herd.model.AlreadyExistsException; import org.finra.herd.model.annotation.PublishNotificationMessages; import org.finra.herd.model.api.xml.Attribute; import org.finra.herd.model.api.xml.BusinessObjectData; import org.finra.herd.model.api.xml.BusinessObjectDataStorageUnitKey; import org.finra.herd.model.api.xml.BusinessObjectDefinitionCreateRequest; import org.finra.herd.model.api.xml.BusinessObjectDefinitionKey; import org.finra.herd.model.api.xml.BusinessObjectFormat; import org.finra.herd.model.api.xml.BusinessObjectFormatCreateRequest; import org.finra.herd.model.api.xml.BusinessObjectFormatKey; import org.finra.herd.model.api.xml.RelationalTableRegistrationCreateRequest; import org.finra.herd.model.api.xml.Schema; import org.finra.herd.model.api.xml.SchemaColumn; import org.finra.herd.model.dto.ConfigurationValue; import org.finra.herd.model.dto.RelationalStorageAttributesDto; import org.finra.herd.model.dto.RelationalTableRegistrationDto; import org.finra.herd.model.jpa.BusinessObjectDataEntity; import org.finra.herd.model.jpa.BusinessObjectDataStatusEntity; import org.finra.herd.model.jpa.BusinessObjectDefinitionEntity; import org.finra.herd.model.jpa.BusinessObjectFormatEntity; import org.finra.herd.model.jpa.FileTypeEntity; import org.finra.herd.model.jpa.StorageEntity; import org.finra.herd.model.jpa.StoragePlatformEntity; import org.finra.herd.model.jpa.StorageUnitEntity; import org.finra.herd.model.jpa.StorageUnitStatusEntity; import org.finra.herd.service.BusinessObjectFormatService; import org.finra.herd.service.MessageNotificationEventService; import org.finra.herd.service.RelationalTableRegistrationHelperService; import org.finra.herd.service.helper.AlternateKeyHelper; import org.finra.herd.service.helper.BusinessObjectDataHelper; import org.finra.herd.service.helper.BusinessObjectDataStatusDaoHelper; import org.finra.herd.service.helper.BusinessObjectDefinitionDaoHelper; import org.finra.herd.service.helper.BusinessObjectFormatDaoHelper; import org.finra.herd.service.helper.BusinessObjectFormatHelper; import org.finra.herd.service.helper.DataProviderDaoHelper; import org.finra.herd.service.helper.NamespaceDaoHelper; import org.finra.herd.service.helper.SearchIndexUpdateHelper; import org.finra.herd.service.helper.StorageDaoHelper; import org.finra.herd.service.helper.StorageHelper; import org.finra.herd.service.helper.StorageUnitDaoHelper; import org.finra.herd.service.helper.StorageUnitStatusDaoHelper; /** * An implementation of the helper service class for the relational table registration service. */ @Service @Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME) public class RelationalTableRegistrationHelperServiceImpl implements RelationalTableRegistrationHelperService { private static final Logger LOGGER = LoggerFactory .getLogger(RelationalTableRegistrationHelperServiceImpl.class); @Autowired private AlternateKeyHelper alternateKeyHelper; @Autowired private BusinessObjectDataDao businessObjectDataDao; @Autowired private BusinessObjectDataHelper businessObjectDataHelper; @Autowired private BusinessObjectDataStatusDaoHelper businessObjectDataStatusDaoHelper; @Autowired private BusinessObjectDefinitionDao businessObjectDefinitionDao; @Autowired private BusinessObjectDefinitionDaoHelper businessObjectDefinitionDaoHelper; @Autowired private BusinessObjectFormatDao businessObjectFormatDao; @Autowired private BusinessObjectFormatDaoHelper businessObjectFormatDaoHelper; @Autowired private BusinessObjectFormatHelper businessObjectFormatHelper; @Autowired private BusinessObjectFormatService businessObjectFormatService; @Autowired private ConfigurationHelper configurationHelper; @Autowired private CredStashHelper credStashHelper; @Autowired private DataProviderDaoHelper dataProviderDaoHelper; @Autowired private JsonHelper jsonHelper; @Autowired private MessageNotificationEventService messageNotificationEventService; @Autowired private NamespaceDaoHelper namespaceDaoHelper; @Autowired private SearchIndexUpdateHelper searchIndexUpdateHelper; @Autowired private StorageDaoHelper storageDaoHelper; @Autowired private StorageHelper storageHelper; @Autowired private StorageUnitDaoHelper storageUnitDaoHelper; @Autowired private StorageUnitStatusDaoHelper storageUnitStatusDaoHelper; @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public RelationalStorageAttributesDto prepareForRelationalTableRegistration( RelationalTableRegistrationCreateRequest relationalTableRegistrationCreateRequest, Boolean appendToExistingBusinessObjectDefinition) { return prepareForRelationalTableRegistrationImpl(relationalTableRegistrationCreateRequest, appendToExistingBusinessObjectDefinition); } @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public RelationalTableRegistrationDto prepareForRelationalTableSchemaUpdate( BusinessObjectDataStorageUnitKey storageUnitKey) { return prepareForRelationalTableSchemaUpdateImpl(storageUnitKey); } @PublishNotificationMessages @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public BusinessObjectData registerRelationalTable( RelationalTableRegistrationCreateRequest relationalTableRegistrationCreateRequest, List<SchemaColumn> schemaColumns, Boolean appendToExistingBusinessObjectDefinition) { return registerRelationalTableImpl(relationalTableRegistrationCreateRequest, schemaColumns, appendToExistingBusinessObjectDefinition); } @Override @Transactional(propagation = Propagation.NOT_SUPPORTED) public List<SchemaColumn> retrieveRelationalTableColumns( RelationalStorageAttributesDto relationalStorageAttributesDto, String relationalSchemaName, String relationalTableName) { return retrieveRelationalTableColumnsImpl(relationalStorageAttributesDto, relationalSchemaName, relationalTableName); } @PublishNotificationMessages @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public BusinessObjectData updateRelationalTableSchema( RelationalTableRegistrationDto relationalTableRegistrationDto, List<SchemaColumn> schemaColumns) { return updateRelationalTableSchemaImpl(relationalTableRegistrationDto, schemaColumns); } @Override @Transactional(propagation = Propagation.NOT_SUPPORTED) public void validateAndTrimRelationalTableRegistrationCreateRequest( RelationalTableRegistrationCreateRequest relationalTableRegistrationCreateRequest) { validateAndTrimRelationalTableRegistrationCreateRequestImpl(relationalTableRegistrationCreateRequest); } /** * Gets a password value that should be used to connect to the relational storage. * * @param relationalStorageAttributesDto the relational storage attributes DTO * * @return the password value */ String getPassword(RelationalStorageAttributesDto relationalStorageAttributesDto) { // Default password value to null. String password = null; // Check if we need to get a password value from the credstash. if (StringUtils.isNotBlank(relationalStorageAttributesDto.getJdbcUserCredentialName())) { final String credStashEncryptionContext = configurationHelper .getProperty(ConfigurationValue.CREDSTASH_RELATIONAL_STORAGE_ENCRYPTION_CONTEXT); try { password = credStashHelper.getCredentialFromCredStash(credStashEncryptionContext, relationalStorageAttributesDto.getJdbcUserCredentialName()); } catch (CredStashGetCredentialFailedException e) { throw new IllegalStateException(e); } } return password; } /** * Prepares for relational table registration by validating database entities per specified relational table registration create request. This method * returns storage attributes required to perform relation table registration. * * @param relationalTableRegistrationCreateRequest the relational table registration create request * @param appendToExistingBusinessObjectDefinition boolean flag that determines if the format should be appended to an existing business object definition * * @return the relational storage attributes DTO */ RelationalStorageAttributesDto prepareForRelationalTableRegistrationImpl( RelationalTableRegistrationCreateRequest relationalTableRegistrationCreateRequest, Boolean appendToExistingBusinessObjectDefinition) { // Validate that specified namespace exists. namespaceDaoHelper.getNamespaceEntity(relationalTableRegistrationCreateRequest.getNamespace()); // Create a business object definition key. BusinessObjectDefinitionKey businessObjectDefinitionKey = new BusinessObjectDefinitionKey( relationalTableRegistrationCreateRequest.getNamespace(), relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionName()); // Ensure that a business object definition with the specified key doesn't already exist. if (BooleanUtils.isNotTrue(appendToExistingBusinessObjectDefinition) && businessObjectDefinitionDao .getBusinessObjectDefinitionByKey(businessObjectDefinitionKey) != null) { throw new AlreadyExistsException(String.format( "Business object definition with name \"%s\" already exists for namespace \"%s\".", businessObjectDefinitionKey.getBusinessObjectDefinitionName(), businessObjectDefinitionKey.getNamespace())); } // Get the latest format version for this business format, if it exists. BusinessObjectFormatEntity latestVersionBusinessObjectFormatEntity = businessObjectFormatDao .getBusinessObjectFormatByAltKey( new BusinessObjectFormatKey(relationalTableRegistrationCreateRequest.getNamespace(), relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionName(), relationalTableRegistrationCreateRequest.getBusinessObjectFormatUsage(), FileTypeEntity.RELATIONAL_TABLE_FILE_TYPE, null)); // If the latest version exists, fail with an already exists exception. if (latestVersionBusinessObjectFormatEntity != null) { throw new AlreadyExistsException(String.format( "Format with file type \"%s\" and usage \"%s\" already exists for business object definition \"%s\".", latestVersionBusinessObjectFormatEntity.getFileType().getCode(), latestVersionBusinessObjectFormatEntity.getUsage(), latestVersionBusinessObjectFormatEntity.getBusinessObjectDefinition().getName())); } // Validate that specified data provider exists. dataProviderDaoHelper.getDataProviderEntity(relationalTableRegistrationCreateRequest.getDataProviderName()); // Get the storage. StorageEntity storageEntity = storageDaoHelper .getStorageEntity(relationalTableRegistrationCreateRequest.getStorageName()); // Only RELATIONAL storage platform is supported for the relational table registration feature. Assert.isTrue(storageEntity.getStoragePlatform().getName().equals(StoragePlatformEntity.RELATIONAL), String.format( "Cannot register relational table in \"%s\" storage of %s storage platform type. Only %s storage platform type is supported by this feature.", storageEntity.getName(), storageEntity.getStoragePlatform().getName(), StoragePlatformEntity.RELATIONAL)); // Get and return the relational storage attributes required to access relation table schema. return getRelationalStorageAttributes(storageEntity); } /** * Prepares for relational table schema update by validating database entities per specified storage unit key. This method returns a relational table * registration DTO which contains attributes required to retrieve the current relation table schema. * * @param storageUnitKey the storage unit key for the relational table registration * * @return the relational table registration DTO */ RelationalTableRegistrationDto prepareForRelationalTableSchemaUpdateImpl( BusinessObjectDataStorageUnitKey storageUnitKey) { // Log the business object format create request. LOGGER.info("Checking relational table registration for schema update... storageUnitKey={}", jsonHelper.objectToJson(storageUnitKey)); // Get the storage unit. StorageUnitEntity storageUnitEntity = storageUnitDaoHelper.getStorageUnitEntityByKey(storageUnitKey); // Get the business object format entity for this relation table registration. BusinessObjectFormatEntity businessObjectFormatEntity = storageUnitEntity.getBusinessObjectData() .getBusinessObjectFormat(); // Get relational schema name from the business object format. This business object format attribute is required and must have a non-blank value. String relationalSchemaName = businessObjectFormatDaoHelper.getBusinessObjectFormatAttributeValueByName( configurationHelper.getProperty( ConfigurationValue.BUSINESS_OBJECT_FORMAT_ATTRIBUTE_NAME_RELATIONAL_SCHEMA_NAME), businessObjectFormatEntity, true, true); // Get relational table name from the business object format. This business object format attribute is required and must have a non-blank value. String relationalTableName = businessObjectFormatDaoHelper.getBusinessObjectFormatAttributeValueByName( configurationHelper.getProperty( ConfigurationValue.BUSINESS_OBJECT_FORMAT_ATTRIBUTE_NAME_RELATIONAL_TABLE_NAME), businessObjectFormatEntity, true, true); // Get relational storage attributes required to access relation table schema. RelationalStorageAttributesDto relationalStorageAttributesDto = getRelationalStorageAttributes( storageUnitEntity.getStorage()); // Get business object format for the relational table registration. BusinessObjectFormat businessObjectFormat = businessObjectFormatHelper .createBusinessObjectFormatFromEntity(businessObjectFormatEntity); // Create and return a relational storage attributes DTO. return new RelationalTableRegistrationDto(storageUnitKey, relationalStorageAttributesDto, relationalSchemaName, relationalTableName, businessObjectFormat); } /** * Creates a new relational table registration. The relation table registration includes creation of the following entities: <ul> <li>a business object * definition</li> <li>a business object format with the specified schema columns</li> <li>a business object data</li> <li>a storage unit that links * together the business object data with the storage specified in the create request</li> </ul> * * @param relationalTableRegistrationCreateRequest the relational table registration create request * @param schemaColumns the list of schema columns * @param appendToExistingBusinessObjectDefinition boolean flag that determines if the format should be appended to an existing business object definition * * @return the information for the newly created business object data */ BusinessObjectData registerRelationalTableImpl( RelationalTableRegistrationCreateRequest relationalTableRegistrationCreateRequest, List<SchemaColumn> schemaColumns, Boolean appendToExistingBusinessObjectDefinition) { BusinessObjectDefinitionEntity businessObjectDefinitionEntity; // If we are appending the new business object format to an already existing business object definition, // then get the business object definition with the information in the relational table registration create request, // else create a new business object definition with the information in the relational table registration create request. if (BooleanUtils.isTrue(appendToExistingBusinessObjectDefinition)) { // Get the existing business object definition businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity( new BusinessObjectDefinitionKey(relationalTableRegistrationCreateRequest.getNamespace(), relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionName())); } else { // Create a business object definition. businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper .createBusinessObjectDefinitionEntity(new BusinessObjectDefinitionCreateRequest( relationalTableRegistrationCreateRequest.getNamespace(), relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionName(), relationalTableRegistrationCreateRequest.getDataProviderName(), null, relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionDisplayName(), null)); } // Notify the search index that a business object definition is created. LOGGER.info( "Create the business object definition in the search index associated with the business object definition being created." + " businessObjectDefinitionId=\"{}\", searchIndexUpdateType=\"{}\"", businessObjectDefinitionEntity.getId(), SEARCH_INDEX_UPDATE_TYPE_CREATE); searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_CREATE); // Build a business object format create request. // Store the relational table name as a business object format attribute per attribute name configured in the system. BusinessObjectFormatCreateRequest businessObjectFormatCreateRequest = new BusinessObjectFormatCreateRequest(); businessObjectFormatCreateRequest.setNamespace(relationalTableRegistrationCreateRequest.getNamespace()); businessObjectFormatCreateRequest.setBusinessObjectDefinitionName( relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionName()); businessObjectFormatCreateRequest.setBusinessObjectFormatUsage( relationalTableRegistrationCreateRequest.getBusinessObjectFormatUsage()); businessObjectFormatCreateRequest .setBusinessObjectFormatFileType(FileTypeEntity.RELATIONAL_TABLE_FILE_TYPE); businessObjectFormatCreateRequest .setPartitionKey(BusinessObjectDataServiceImpl.NO_PARTITIONING_PARTITION_KEY); businessObjectFormatCreateRequest.setAttributes(Arrays.asList( new Attribute( configurationHelper.getProperty( ConfigurationValue.BUSINESS_OBJECT_FORMAT_ATTRIBUTE_NAME_RELATIONAL_SCHEMA_NAME), relationalTableRegistrationCreateRequest.getRelationalSchemaName()), new Attribute( configurationHelper.getProperty( ConfigurationValue.BUSINESS_OBJECT_FORMAT_ATTRIBUTE_NAME_RELATIONAL_TABLE_NAME), relationalTableRegistrationCreateRequest.getRelationalTableName()))); businessObjectFormatCreateRequest .setSchema(new Schema(schemaColumns, null, "", null, null, null, null, null)); // Log the business object format create request. LOGGER.info("Registering relational table... businessObjectFormatCreateRequest={}", jsonHelper.objectToJson(businessObjectFormatCreateRequest)); // Create a business object format. BusinessObjectFormat businessObjectFormat = businessObjectFormatService .createBusinessObjectFormat(businessObjectFormatCreateRequest); // Retrieve the newly created business object format entity. BusinessObjectFormatEntity businessObjectFormatEntity = businessObjectFormatDaoHelper .getBusinessObjectFormatEntity( businessObjectFormatHelper.getBusinessObjectFormatKey(businessObjectFormat)); // Allow non-backwards-compatible schema changes. businessObjectFormatEntity.setAllowNonBackwardsCompatibleChanges(true); businessObjectFormatDao.saveAndRefresh(businessObjectFormatEntity); // Get a business object data status entity for the VALID status. BusinessObjectDataStatusEntity businessObjectDataStatusEntity = businessObjectDataStatusDaoHelper .getBusinessObjectDataStatusEntity(BusinessObjectDataStatusEntity.VALID); // Create a business object data entity. BusinessObjectDataEntity businessObjectDataEntity = new BusinessObjectDataEntity(); businessObjectDataEntity.setBusinessObjectFormat(businessObjectFormatEntity); businessObjectDataEntity.setStatus(businessObjectDataStatusEntity); businessObjectDataEntity.setVersion(0); businessObjectDataEntity.setLatestVersion(true); businessObjectDataEntity.setPartitionValue(BusinessObjectDataServiceImpl.NO_PARTITIONING_PARTITION_VALUE); // Get a storage unit status entity for the ENABLED status. StorageUnitStatusEntity storageUnitStatusEntity = storageUnitStatusDaoHelper .getStorageUnitStatusEntity(StorageUnitStatusEntity.ENABLED); // Get the storage. StorageEntity storageEntity = storageDaoHelper .getStorageEntity(relationalTableRegistrationCreateRequest.getStorageName()); // Create a storage unit entity. StorageUnitEntity storageUnitEntity = new StorageUnitEntity(); storageUnitEntity.setStorage(storageEntity); storageUnitEntity.setBusinessObjectData(businessObjectDataEntity); storageUnitDaoHelper.setStorageUnitStatus(storageUnitEntity, storageUnitStatusEntity); businessObjectDataEntity.setStorageUnits(Collections.singletonList(storageUnitEntity)); // Persist the newly created business object data entity. businessObjectDataEntity = businessObjectDataDao.saveAndRefresh(businessObjectDataEntity); // Create a status change notification to be sent on create business object data event. messageNotificationEventService.processBusinessObjectDataStatusChangeNotificationEvent( businessObjectDataHelper.getBusinessObjectDataKey(businessObjectDataEntity), businessObjectDataStatusEntity.getCode(), null); // Create and return business object data information from the newly created business object data entity. return businessObjectDataHelper.createBusinessObjectDataFromEntity(businessObjectDataEntity); } /** * Retrieves a list of actual schema columns for the specified relational table. This method uses actual JDBC connection to retrieve a description of table * columns. * * @param relationalStorageAttributesDto the relational storage attributes DTO * @param relationalSchemaName the name of the relational database schema * @param relationalTableName the name of the relational table * * @return the list of schema columns for the specified relational table */ List<SchemaColumn> retrieveRelationalTableColumnsImpl( RelationalStorageAttributesDto relationalStorageAttributesDto, String relationalSchemaName, String relationalTableName) { // Get the JDBC password value. String password = getPassword(relationalStorageAttributesDto); // Create and initialize a driver manager data source (a simple implementation of the standard JDBC interface). // We only support PostgreSQL database type. DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource(); driverManagerDataSource.setUrl(relationalStorageAttributesDto.getJdbcUrl()); driverManagerDataSource.setUsername(relationalStorageAttributesDto.getJdbcUsername()); driverManagerDataSource.setPassword(password); driverManagerDataSource.setDriverClassName(JdbcServiceImpl.DRIVER_POSTGRES); // Create an empty result list. List<SchemaColumn> schemaColumns = new ArrayList<>(); // Connect to the database and retrieve the relational table columns. try (Connection connection = driverManagerDataSource.getConnection()) { DatabaseMetaData databaseMetaData = connection.getMetaData(); // Check if the specified relational table exists in the database. try (ResultSet tables = databaseMetaData.getTables(null, relationalSchemaName, relationalTableName, null)) { Assert.isTrue(tables.next(), String.format( "Relational table with \"%s\" name not found under \"%s\" schema at jdbc.url=\"%s\" for jdbc.username=\"%s\".", relationalTableName, relationalSchemaName, driverManagerDataSource.getUrl(), driverManagerDataSource.getUsername())); } // Retrieve the relational table columns. try (ResultSet columns = databaseMetaData.getColumns(null, relationalSchemaName, relationalTableName, null)) { while (columns.next()) { SchemaColumn schemaColumn = new SchemaColumn(); schemaColumn.setName(columns.getString("COLUMN_NAME")); schemaColumn.setType(columns.getString("TYPE_NAME")); schemaColumn.setSize(columns.getString("COLUMN_SIZE")); schemaColumn.setRequired(columns.getInt("NULLABLE") == 0); schemaColumn.setDefaultValue(columns.getString("COLUMN_DEF")); schemaColumns.add(schemaColumn); } } } catch (SQLException e) { throw new IllegalArgumentException(String.format( "Failed to retrieve description of a relational table with \"%s\" name under \"%s\" schema " + "at jdbc.url=\"%s\" using jdbc.username=\"%s\". Reason: %s", relationalTableName, relationalSchemaName, driverManagerDataSource.getUrl(), driverManagerDataSource.getUsername(), e.getMessage()), e); } return schemaColumns; } /** * Updates relational table schema for an already existing relational table registration. * * @param relationalTableRegistrationDto the relational table registration DTO * @param schemaColumns the new relational table schema * * @return the information for the business object data created for the updated relational table registration */ BusinessObjectData updateRelationalTableSchemaImpl( RelationalTableRegistrationDto relationalTableRegistrationDto, List<SchemaColumn> schemaColumns) { // Build a create request for a new version of the business object format. BusinessObjectFormatCreateRequest businessObjectFormatCreateRequest = new BusinessObjectFormatCreateRequest(); businessObjectFormatCreateRequest .setNamespace(relationalTableRegistrationDto.getBusinessObjectFormat().getNamespace()); businessObjectFormatCreateRequest.setBusinessObjectDefinitionName( relationalTableRegistrationDto.getBusinessObjectFormat().getBusinessObjectDefinitionName()); businessObjectFormatCreateRequest.setBusinessObjectFormatUsage( relationalTableRegistrationDto.getBusinessObjectFormat().getBusinessObjectFormatUsage()); businessObjectFormatCreateRequest.setBusinessObjectFormatFileType( relationalTableRegistrationDto.getBusinessObjectFormat().getBusinessObjectFormatFileType()); businessObjectFormatCreateRequest .setPartitionKey(relationalTableRegistrationDto.getBusinessObjectFormat().getPartitionKey()); businessObjectFormatCreateRequest .setAttributes(relationalTableRegistrationDto.getBusinessObjectFormat().getAttributes()); businessObjectFormatCreateRequest .setSchema(new Schema(schemaColumns, null, "", null, null, null, null, null)); // Log the relational table registration DTO along with the business object format create request. LOGGER.info( "Updating relational table schema... relationalTableRegistrationDto={} businessObjectFormatCreateRequest={}", jsonHelper.objectToJson(relationalTableRegistrationDto), jsonHelper.objectToJson(businessObjectFormatCreateRequest)); // Create a new version of the business object format. BusinessObjectFormat businessObjectFormat = businessObjectFormatService .createBusinessObjectFormat(businessObjectFormatCreateRequest); // Retrieve the newly created business object format entity. BusinessObjectFormatEntity businessObjectFormatEntity = businessObjectFormatDaoHelper .getBusinessObjectFormatEntity( businessObjectFormatHelper.getBusinessObjectFormatKey(businessObjectFormat)); // Get a business object data status entity for the VALID status. BusinessObjectDataStatusEntity businessObjectDataStatusEntity = businessObjectDataStatusDaoHelper .getBusinessObjectDataStatusEntity(BusinessObjectDataStatusEntity.VALID); // Create a business object data entity. BusinessObjectDataEntity businessObjectDataEntity = new BusinessObjectDataEntity(); businessObjectDataEntity.setBusinessObjectFormat(businessObjectFormatEntity); businessObjectDataEntity.setStatus(businessObjectDataStatusEntity); businessObjectDataEntity.setVersion(0); businessObjectDataEntity.setLatestVersion(true); businessObjectDataEntity.setPartitionValue(BusinessObjectDataServiceImpl.NO_PARTITIONING_PARTITION_VALUE); // Get a storage unit status entity for the ENABLED status. StorageUnitStatusEntity storageUnitStatusEntity = storageUnitStatusDaoHelper .getStorageUnitStatusEntity(StorageUnitStatusEntity.ENABLED); // Get the storage. StorageEntity storageEntity = storageDaoHelper .getStorageEntity(relationalTableRegistrationDto.getStorageUnitKey().getStorageName()); // Create a storage unit entity. StorageUnitEntity storageUnitEntity = new StorageUnitEntity(); storageUnitEntity.setStorage(storageEntity); storageUnitEntity.setBusinessObjectData(businessObjectDataEntity); storageUnitDaoHelper.setStorageUnitStatus(storageUnitEntity, storageUnitStatusEntity); businessObjectDataEntity.setStorageUnits(Collections.singletonList(storageUnitEntity)); // Persist the newly created business object data entity. businessObjectDataEntity = businessObjectDataDao.saveAndRefresh(businessObjectDataEntity); // Create a status change notification to be sent on create business object data event. messageNotificationEventService.processBusinessObjectDataStatusChangeNotificationEvent( businessObjectDataHelper.getBusinessObjectDataKey(businessObjectDataEntity), businessObjectDataStatusEntity.getCode(), null); // Create and return business object data information from the newly created business object data entity. return businessObjectDataHelper.createBusinessObjectDataFromEntity(businessObjectDataEntity); } /** * Validates a relational table registration create request. This method also trims the request parameters. * * @param relationalTableRegistrationCreateRequest the relational table registration create request */ void validateAndTrimRelationalTableRegistrationCreateRequestImpl( RelationalTableRegistrationCreateRequest relationalTableRegistrationCreateRequest) { Assert.notNull(relationalTableRegistrationCreateRequest, "A relational table registration create request must be specified."); // Validate and trim required parameters. relationalTableRegistrationCreateRequest.setNamespace(alternateKeyHelper .validateStringParameter("namespace", relationalTableRegistrationCreateRequest.getNamespace())); relationalTableRegistrationCreateRequest.setBusinessObjectDefinitionName( alternateKeyHelper.validateStringParameter("business object definition name", relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionName())); relationalTableRegistrationCreateRequest.setBusinessObjectFormatUsage( alternateKeyHelper.validateStringParameter("business object format usage", relationalTableRegistrationCreateRequest.getBusinessObjectFormatUsage())); relationalTableRegistrationCreateRequest.setDataProviderName(alternateKeyHelper.validateStringParameter( "data provider name", relationalTableRegistrationCreateRequest.getDataProviderName())); relationalTableRegistrationCreateRequest.setRelationalSchemaName(alternateKeyHelper.validateStringParameter( "relational schema name", relationalTableRegistrationCreateRequest.getRelationalSchemaName())); relationalTableRegistrationCreateRequest.setRelationalTableName(alternateKeyHelper.validateStringParameter( "relational table name", relationalTableRegistrationCreateRequest.getRelationalTableName())); relationalTableRegistrationCreateRequest.setStorageName(alternateKeyHelper.validateStringParameter( "storage name", relationalTableRegistrationCreateRequest.getStorageName())); // Trim optional business object definition display name, if specified. if (relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionDisplayName() != null) { relationalTableRegistrationCreateRequest.setBusinessObjectDefinitionDisplayName( relationalTableRegistrationCreateRequest.getBusinessObjectDefinitionDisplayName().trim()); } } /** * Returns storage attributes required to access relation table schema. * * @param storageEntity the storage entity * * @return the relational storage attributes DTO */ private RelationalStorageAttributesDto getRelationalStorageAttributes(StorageEntity storageEntity) { // Get JDBC URL for this storage. This storage attribute is required and must have a non-blank value. String jdbcUrl = storageHelper.getStorageAttributeValueByName( configurationHelper.getProperty(ConfigurationValue.STORAGE_ATTRIBUTE_NAME_JDBC_URL), storageEntity, true, true); // Get JDBC username for this storage. This storage attribute is not required and it is allowed to have a blank value. String jdbcUsername = storageHelper.getStorageAttributeValueByName( configurationHelper.getProperty(ConfigurationValue.STORAGE_ATTRIBUTE_NAME_JDBC_USERNAME), storageEntity, false, false); // Get JDBC user credential name for this storage. This storage attribute is not required and it is allowed to have a blank value. String jdbcUserCredentialName = storageHelper.getStorageAttributeValueByName( configurationHelper .getProperty(ConfigurationValue.STORAGE_ATTRIBUTE_NAME_JDBC_USER_CREDENTIAL_NAME), storageEntity, false, false); // Create and return a relational storage attributes DTO. return new RelationalStorageAttributesDto(jdbcUrl, jdbcUsername, jdbcUserCredentialName); } }