Subversion Repositories SmartDukaan

Rev

Rev 35830 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
23723 amit.gupta 1
package com.smartdukaan.cron.config;
2
 
32185 amit.gupta 3
import com.fasterxml.jackson.databind.DeserializationFeature;
24433 amit.gupta 4
import com.fasterxml.jackson.databind.ObjectMapper;
5
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
6
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
29859 amit.gupta 7
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
24433 amit.gupta 8
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
29859 amit.gupta 9
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
24433 amit.gupta 10
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
11
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
25721 tejbeer 12
import com.google.gson.Gson;
13
import com.google.gson.GsonBuilder;
29838 tejbeer 14
import com.spice.profitmandi.dao.convertor.LocalDateJsonConverter;
25721 tejbeer 15
import com.spice.profitmandi.dao.convertor.LocalDateTimeJsonConverter;
23738 amit.gupta 16
import com.spice.profitmandi.dao.repository.dtr.Mongo;
34690 amit.gupta 17
 
35393 amit 18
import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;
34690 amit.gupta 19
import com.zaxxer.hikari.HikariConfig;
20
import com.zaxxer.hikari.HikariDataSource;
30307 amit.gupta 21
import org.apache.logging.log4j.LogManager;
22
import org.apache.logging.log4j.Logger;
23
import org.hibernate.SessionFactory;
24
import org.springframework.beans.factory.annotation.Autowired;
25
import org.springframework.beans.factory.annotation.Value;
35832 amit 26
import org.springframework.context.annotation.Bean;
27
import org.springframework.context.annotation.ComponentScan;
28
import org.springframework.context.annotation.Configuration;
29
import org.springframework.context.annotation.Primary;
34690 amit.gupta 30
import org.springframework.core.env.Environment;
30307 amit.gupta 31
import org.springframework.jdbc.datasource.DriverManagerDataSource;
32
import org.springframework.orm.hibernate5.HibernateTransactionManager;
33
import org.springframework.orm.hibernate5.LocalSessionFactoryBuilder;
34
import org.springframework.transaction.annotation.EnableTransactionManagement;
23738 amit.gupta 35
 
35393 amit 36
import javax.annotation.PreDestroy;
30307 amit.gupta 37
import javax.sql.DataSource;
35393 amit 38
import java.sql.Driver;
39
import java.sql.DriverManager;
40
import java.sql.SQLException;
30307 amit.gupta 41
import java.time.LocalDate;
42
import java.time.LocalDateTime;
43
import java.time.format.DateTimeFormatter;
44
import java.time.format.DateTimeFormatterBuilder;
35393 amit 45
import java.util.Enumeration;
30307 amit.gupta 46
import java.util.Properties;
47
 
23723 amit.gupta 48
@Configuration
49
@EnableTransactionManagement
23755 amit.gupta 50
@ComponentScan("com.spice.profitmandi.*")
23723 amit.gupta 51
public class DBConfig {
52
 
25721 tejbeer 53
	private static final Logger LOGGER = LogManager.getLogger(DBConfig.class);
23723 amit.gupta 54
 
34690 amit.gupta 55
	// Hibernate Property Keys
23755 amit.gupta 56
	private static final String HIBERNATE_DIALECT = "hibernate.dialect";
57
	private static final String HIBERNATE_SHOW_SQL = "hibernate.show_sql";
58
	private static final String HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
59
	private static final String HIBERNATE_JDBC_BATCH_SIZE = "hibernate.jdbc.batch_size";
23723 amit.gupta 60
 
34690 amit.gupta 61
		// HikariCP Properties
62
	private static final String HIKARI_MAX_POOL_SIZE = "hikari.maximumPoolSize";
63
	private static final String HIKARI_MIN_IDLE = "hikari.minimumIdle";
64
	private static final String HIKARI_IDLE_TIMEOUT = "hikari.idleTimeout";
65
	private static final String HIKARI_MAX_LIFETIME = "hikari.maxLifetime";
66
	private static final String HIKARI_CONNECTION_TIMEOUT = "hikari.connectionTimeout";
23723 amit.gupta 67
 
68
 
34690 amit.gupta 69
	// Injected DB Properties
23723 amit.gupta 70
	@Value("${hibernate.driver.class}")
71
	private String hibernateDriverClass;
72
 
73
	@Value("${hibernate.url}")
74
	private String hibernateUrl;
75
 
76
	@Value("${hibernate.user.name}")
77
	private String hibernateUserName;
78
 
79
	@Value("${hibernate.password}")
80
	private String hibernatePassword;
81
 
82
	@Value("${hibernate.dialect}")
83
	private String hibernateDialect;
84
 
85
	@Value("${hibernate.show_sql}")
86
	private String hibernateShowSql;
87
 
88
	@Value("${hibernate.format_sql}")
89
	private String hibernateFormatSql;
90
 
91
	@Value("${hibernate.jdbc.batch_size}")
92
	private String hibernateBatchSize;
93
 
35828 amit 94
	@Value("${hibernate.order_inserts:true}")
95
	private String hibernateOrderInserts;
96
 
97
	@Value("${hibernate.order_updates:true}")
98
	private String hibernateOrderUpdates;
99
 
34690 amit.gupta 100
	// Mongo Config
23738 amit.gupta 101
	@Value("${mongo.host}")
102
	private String mongoHost;
23723 amit.gupta 103
 
23738 amit.gupta 104
	@Value("${content.mongo.host}")
105
	private String contentMongoHost;
25721 tejbeer 106
 
34690 amit.gupta 107
	@Autowired
108
	private Environment env;
109
 
110
	/**
111
	 * Primary DataSource using DriverManager (can be replaced with HikariDataSource)
112
	 */
23898 amit.gupta 113
	@Primary
35393 amit 114
	@Bean(name = "dataSource", destroyMethod = "close")
115
	public HikariDataSource dataSource() {
34690 amit.gupta 116
		HikariConfig config = new HikariConfig();
117
		config.setDriverClassName(hibernateDriverClass);
118
		config.setJdbcUrl(hibernateUrl);
119
		config.setUsername(hibernateUserName);
120
		config.setPassword(hibernatePassword);
121
 
122
		config.setMaximumPoolSize(Integer.parseInt(env.getProperty(HIKARI_MAX_POOL_SIZE, "20")));
123
		config.setMinimumIdle(Integer.parseInt(env.getProperty(HIKARI_MIN_IDLE, "2")));
124
		config.setIdleTimeout(Long.parseLong(env.getProperty(HIKARI_IDLE_TIMEOUT, "30000")));
125
		config.setMaxLifetime(Long.parseLong(env.getProperty(HIKARI_MAX_LIFETIME, "1800000")));
126
		config.setConnectionTimeout(Long.parseLong(env.getProperty(HIKARI_CONNECTION_TIMEOUT, "30000")));
127
 
128
		config.setPoolName("HikariPool");
35586 amit 129
		config.setAutoCommit(false);
34690 amit.gupta 130
 
131
 
132
		HikariDataSource dataSource = new HikariDataSource(config);
133
		LOGGER.info("HikariDataSource initialized with JDBC URL {}", hibernateUrl);
23723 amit.gupta 134
		return dataSource;
135
	}
25721 tejbeer 136
 
34690 amit.gupta 137
	/**
138
	 * Configure Hibernate properties
139
	 */
24433 amit.gupta 140
	@Bean
23723 amit.gupta 141
	public Properties getHibernateProperties() {
142
		Properties dbProperties = new Properties();
143
		dbProperties.put(HIBERNATE_DIALECT, hibernateDialect);
144
		dbProperties.put(HIBERNATE_SHOW_SQL, hibernateShowSql);
145
		dbProperties.put(HIBERNATE_FORMAT_SQL, hibernateFormatSql);
146
		dbProperties.put(HIBERNATE_JDBC_BATCH_SIZE, hibernateBatchSize);
35828 amit 147
		dbProperties.put("hibernate.order_inserts", hibernateOrderInserts);
148
		dbProperties.put("hibernate.order_updates", hibernateOrderUpdates);
23723 amit.gupta 149
		return dbProperties;
150
	}
25721 tejbeer 151
 
34690 amit.gupta 152
	/**
153
	 * Configure Hibernate SessionFactory
154
	 */
23898 amit.gupta 155
	@Primary
34690 amit.gupta 156
	@Bean(name = "sessionFactory")
23723 amit.gupta 157
	@Autowired
158
	public SessionFactory getSessionFactory(DataSource dataSource) {
159
		LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
160
		sessionBuilder.addProperties(getHibernateProperties());
161
		sessionBuilder.scanPackages("com.spice.profitmandi.dao.*");
34690 amit.gupta 162
		LOGGER.info("SessionFactory created");
23723 amit.gupta 163
		return sessionBuilder.buildSessionFactory();
164
	}
25721 tejbeer 165
 
34690 amit.gupta 166
	/**
167
	 * Transaction Manager
168
	 */
23898 amit.gupta 169
	@Primary
34690 amit.gupta 170
	@Bean(name = "transactionManager")
23723 amit.gupta 171
	@Autowired
172
	public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
173
		HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
34690 amit.gupta 174
		LOGGER.info("TransactionManager created");
23723 amit.gupta 175
		return transactionManager;
176
	}
25721 tejbeer 177
 
34690 amit.gupta 178
	/**
179
	 * ObjectMapper Bean with Java 8 Time module config
180
	 */
23738 amit.gupta 181
	@Bean
34690 amit.gupta 182
	public ObjectMapper objectMapper() {
183
		DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
184
				.parseCaseInsensitive()
185
				.append(DateTimeFormatter.ISO_LOCAL_DATE)
186
				.optionalStart().appendLiteral('T').optionalEnd()
187
				.appendLiteral(' ')
188
				.append(DateTimeFormatter.ISO_LOCAL_TIME)
189
				.toFormatter();
190
 
191
		DateTimeFormatter standardFormatter = new DateTimeFormatterBuilder()
192
				.parseCaseInsensitive()
193
				.append(DateTimeFormatter.ISO_LOCAL_DATE)
194
				.appendLiteral('T')
195
				.append(DateTimeFormatter.ISO_LOCAL_TIME)
196
				.toFormatter();
197
 
198
		JavaTimeModule javaTimeModule = new JavaTimeModule();
199
		javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(standardFormatter));
200
		javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
201
		javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
202
		javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
203
 
204
		ObjectMapper mapper = new ObjectMapper()
205
				.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
206
				.registerModule(new ParameterNamesModule())
207
				.registerModule(new Jdk8Module())
208
				.registerModule(javaTimeModule);
209
 
210
		LOGGER.info("ObjectMapper configured");
211
		return mapper;
212
	}
213
 
214
	/**
215
	 * Mongo Client Bean
216
	 */
35393 amit 217
	@Bean(destroyMethod = "close")
23738 amit.gupta 218
	public Mongo mongoClient(SessionFactory sessionFactory) {
219
		return new Mongo(mongoHost, contentMongoHost);
220
	}
25721 tejbeer 221
 
34690 amit.gupta 222
	/**
223
	 * Gson Bean for LocalDate and LocalDateTime
224
	 */
25721 tejbeer 225
	@Bean(name = "gson")
226
	public Gson gson() {
34690 amit.gupta 227
		Gson gson = new GsonBuilder()
228
				.serializeNulls()
29838 tejbeer 229
				.registerTypeAdapter(LocalDate.class, new LocalDateJsonConverter())
34690 amit.gupta 230
				.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeJsonConverter())
231
				.create();
232
		LOGGER.info("Gson configured");
25721 tejbeer 233
		return gson;
234
	}
35393 amit 235
 
236
	/**
237
	 * Cleanup method to prevent memory leaks on shutdown.
238
	 * Deregisters JDBC drivers and stops MySQL cleanup thread.
239
	 */
240
	@PreDestroy
241
	public void cleanup() {
242
		LOGGER.info("DBConfig cleanup started...");
243
 
244
		// Stop MySQL AbandonedConnectionCleanupThread
245
		try {
246
			AbandonedConnectionCleanupThread.checkedShutdown();
247
			LOGGER.info("MySQL AbandonedConnectionCleanupThread stopped");
248
		} catch (Exception e) {
249
			LOGGER.error("Error stopping MySQL cleanup thread", e);
250
		}
251
 
252
		// Deregister JDBC drivers loaded by this webapp's classloader
253
		ClassLoader cl = Thread.currentThread().getContextClassLoader();
254
		Enumeration<Driver> drivers = DriverManager.getDrivers();
255
		while (drivers.hasMoreElements()) {
256
			Driver driver = drivers.nextElement();
257
			if (driver.getClass().getClassLoader() == cl) {
258
				try {
259
					DriverManager.deregisterDriver(driver);
260
					LOGGER.info("Deregistered JDBC driver: {}", driver);
261
				} catch (SQLException e) {
262
					LOGGER.error("Error deregistering JDBC driver {}", driver, e);
263
				}
264
			}
265
		}
266
 
267
		LOGGER.info("DBConfig cleanup completed");
268
	}
23723 amit.gupta 269
}