[JAVA] Since the reading of JdbcCodeList of TERASOLUNA is slow, I tried to register multiple at once.

TERASOLUNA's JdbcCodeList is a function to register the result of SQL search from the database as a code list, and I think it is often used. It's not a big deal with one or two codelists, but when the number of codelists reaches hundreds of classes, the time it takes to start up becomes unbearable.

So I wondered if I could register multiple code lists at once with ʻUNION ALL` as shown below.

SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_ORDERSTATUS'
UNION ALL
SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_HOGE'
ORDER BY code_bean_name, code_id

Since the code list has 1 code list and 1 bean definition, it is necessary to dynamically add the bean definition in order to register multiple code lists. ʻOrg.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessorIt seems that you can add beans dynamically by creating an implementation class for the interface. If you access the DB from the implementation class of thisBeanDefinitionRegistryPostProcessor` and register the Bean of the code list, you can do what you want.

However, when I actually run it, DB access is not good. Apparently, at the timing when BeanDefinitionRegistryPostProcessor works, it seems that the placeholder like$ {hogehoge}of Bean definition is not resolved, and the string before DB connection string etc. is set from the property ($). {hogehoge}itself) has been taken and it seems that I can not connect well. If you do not use placeholders in the DataSource definition and describe the connection string etc. directly in the Bean definition, you can make a DB connection, but writing directly in XML is not good.

Therefore, I gave up on completing with only the implementation class of BeanDefinitionRegistryPostProcessor and divided it into two stages. The implementation class of BeanDefinitionRegistryPostProcessor defines only the bean definition of the required code list. (However, the contents of the code list are empty) Access the DB with another class @PostConstruct and set the value map in the empty code list. The implementation image is as follows.

CustomBeanDefinitionRegistryPostProcessor.java


/**
 *
 */
package xxxxxx.yyyyyy.zzzzzz.app.welcome;

import java.util.List;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.terasoluna.gfw.common.codelist.SimpleMapCodeList;

/**
 * @author toshio
 *
 */
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
	private List<String> codeListNames;

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		if (codeListNames != null) {
			for (String codeBeanName : codeListNames) {
				BeanDefinition beanDefinition = new RootBeanDefinition(SimpleMapCodeList.class);
				registry.registerBeanDefinition(codeBeanName, beanDefinition);
			}
		}
	}

	/**
	 * @param codeListNames set codeListNames
	 */
	public void setCodeListNames(List<String> codeListNames) {
		this.codeListNames = codeListNames;
	}

}

CustomCodeListLoader.java


/**
 *
 */
package xxxxxx.yyyyyy.zzzzzz.app.welcome;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.terasoluna.gfw.common.codelist.SimpleMapCodeList;

/**
 * @author toshio
 *
 */
public class CustomCodeListLoader {
	/**
	 * Database access information
	 */
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private ApplicationContext applicationContext;

	/**
	 * SQL Query to access the database
	 */
	private String querySql;

	private List<String> codeListNames;

	/**
	 *
	 */
	private String codeNameColumn;

	/**
	 * property that holds the name of the column of the database holding the value part of the codelist
	 */
	private String valueColumn;

	/**
	 * property that holds the name of the column of the database holding the label part of the codelist
	 */
	private String labelColumn;

	@PostConstruct
	public void afterPropertiesSet() {

		Map<String, Map<String, String>> allMap = new HashMap<String, Map<String, String>>();
		for (String codeName : codeListNames) {
			allMap.put(codeName, new LinkedHashMap<String, String>());
		}

		List<Map<String, Object>> rows = jdbcTemplate.queryForList(querySql);
		for (Map<String, Object> row : rows) {
			Object codeName = row.get(codeNameColumn);
			Object key = row.get(valueColumn);
			Object value = row.get(labelColumn);
			if (codeName != null && key != null && value != null) {
				Map<String, String> map = allMap.get(codeName.toString());
				if (map == null) {
					map = new LinkedHashMap<String, String>();
				}
				map.put(key.toString(), value.toString());
				allMap.put(codeName.toString(), map);
			}
		}

		for (Entry<String, Map<String, String>> codeEnt : allMap.entrySet()) {
			Object codeBean = applicationContext.getBean(codeEnt.getKey());
			if (codeBean instanceof SimpleMapCodeList) {
				SimpleMapCodeList smc = (SimpleMapCodeList) codeBean;
				smc.setMap(codeEnt.getValue());
			}
		}
	}

	/**
	 * Sets JdbcTemplate
	 * @param jdbcTemplate JdbcTemplate instance for fetching code list records
	 */
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	/**
	 * Setter method for labelColumn
	 * @param labelColumn column name for fetch a code label
	 */
	public void setLabelColumn(String labelColumn) {
		this.labelColumn = labelColumn;
	}

	/**
	 * Setter method for valueColumn
	 * @param valueColumn column name for fetch code value
	 */
	public void setValueColumn(String valueColumn) {
		this.valueColumn = valueColumn;
	}

	/**
	 * Setter method for querySql
	 * @param querySql sql for fetching code list records from database
	 */
	public void setQuerySql(String querySql) {
		this.querySql = querySql;
	}

	public void setCodeNameColumn(String codeNameColumn) {
		this.codeNameColumn = codeNameColumn;
	}

	/**
	 * @param codeListNames set codeListNames
	 */
	public void setCodeListNames(List<String> codeListNames) {
		this.codeListNames = codeListNames;
	}

}

projectName-codelist.xml


    <bean class="xxxxxx.yyyyyy.zzzzzz.app.welcome.CustomBeanDefinitionRegistryPostProcessor">
        <property name="codeListNames">
            <list>
                <value>CL_ORDERSTATUS</value>
                <value>CL_HOGE</value>
            </list>
        </property>
    </bean>

    <bean class="xxxxxx.yyyyyy.zzzzzz.app.welcome.CustomCodeListLoader">
        <property name="querySql">
            <value>
                SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_ORDERSTATUS'
                UNION ALL
                SELECT code_bean_name, code_id, code_name FROM t_sample_codes WHERE code_bean_name = 'CL_HOGE'
                ORDER BY code_bean_name, code_id
            </value>
        </property>
        <property name="codeNameColumn" value="code_bean_name"/>
        <property name="valueColumn" value="code_id" />
        <property name="labelColumn" value="code_name" />
        <property name="jdbcTemplate" ref="jdbcTemplateForCodeList" />
        <property name="codeListNames">
            <list>
                <value>CL_ORDERSTATUS</value>
                <value>CL_HOGE</value>
            </list>
        </property>
    </bean>

CREATE TABLE t_sample_codes (
                                code_bean_name varchar(32) not null,
                                code_id        varchar(32) not null,
                                code_name      varchar(256) not null,
                                primary key (code_bean_name, code_id)
                            );

INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_ORDERSTATUS', '1', 'Received');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_ORDERSTATUS', '2', 'Sent');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_ORDERSTATUS', '3', 'Cancelled');

INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_HOGE', '1', 'hoge');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_HOGE', '2', 'hogehoge');
INSERT INTO t_sample_codes(code_bean_name, code_id, code_name) VALUES ('CL_HOGE', '3', 'hogehogehoge');

commit;

Recommended Posts

Since the reading of JdbcCodeList of TERASOLUNA is slow, I tried to register multiple at once.
I tried to create a method to apply multiple filters at once with Java Stream API. Is this okay?
I tried to summarize the state transition of docker
I tried to reduce the capacity of Spring Boot
I tried to create a log reproduction script at the time of apt install
Since the argument of link_to is nil (null) and an unexpected link was generated, I tried to verify it
I tried to summarize the basics of kotlin and java
[Swift] I tried to implement the function of the vending machine
I tried to solve the Ruby karaoke machine problem (there is an example of the answer)
I tried to solve the Ruby bonus drink problem (there is an example of the answer)
I tried to summarize the basic grammar of Ruby briefly
I tried to build the environment of WSL2 + Docker + VSCode
I tried to solve the Ruby bingo card creation problem (there is an example of the answer)
I implemented the code to learn multiple images at once in the Watson Visual Recognition Collection in Java.
Since the Rspec command is troublesome, I tried to make it possible to execute Rspec with one Rake command
I tried to take a look at the flow of Android development environment construction with Android Studio
I tried to summarize what was asked at the site-java edition-
I tried to build the environment of PlantUML Server with Docker
I tried to understand how the rails method "redirect_to" is defined
I tried to check the operation of gRPC server with grpcurl
I tried to understand how the rails method "link_to" is defined
I tried to summarize the methods of Java String and StringBuilder
How to call multiple names at once in the same category
I tried to solve the problem of Google Tech Dev Guide
I tried to explain the method
To you who lament that the conversion of JODConverter + LibreOffice is slow
I tried to summarize the key points of gRPC design and development
[Introduction to Java] I tried to summarize the knowledge that I think is essential
I tried to make full use of the CPU core in Ruby
I tried to visualize the access of Lambda → Athena with AWS X-Ray
I tried to measure and compare the speed of GraalVM with JMH
I tried to summarize the methods used
Since the du command used when the capacity is full is difficult to use, I tried wrapping it with ruby
I tried to implement the Iterator pattern
I tried to summarize the Stream API
What is Docker? I tried to summarize
Since the image of the lock screen of Windows 10 is beautiful, I wanted to make it a slide show of wallpaper
I tried to compare the infrastructure technology of engineers these days with cooking.
I tried to summarize again the devise that was difficult at first sight
[Beginner] I tried to decorate the bar after displaying the details of the hamburger menu
I want to output the day of the week
[Rails] I tried to raise the Rails version from 5.0 to 5.2
I tried to organize the session in Rails
I tried to chew C # (basic of encapsulation)
I want to var_dump the contents of the intent
I tried to set tomcat to run the Servlet.
I tried using the profiler of IntelliJ IDEA
I tried to check the operation of http request (Put) with Talented API Tester
[Beginner's point of view] I tried to solve the FizzBuzz problem "easily" with Ruby!
I tried to investigate the mechanism of Emscripten by using it with the Sudoku solver