Subversion Repositories SmartDukaan

Rev

Rev 35832 | 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")));
36339 amit 127
		config.setLeakDetectionThreshold(30000);
34690 amit.gupta 128
 
129
		config.setPoolName("HikariPool");
35586 amit 130
		config.setAutoCommit(false);
34690 amit.gupta 131
 
132
 
133
		HikariDataSource dataSource = new HikariDataSource(config);
134
		LOGGER.info("HikariDataSource initialized with JDBC URL {}", hibernateUrl);
23723 amit.gupta 135
		return dataSource;
136
	}
25721 tejbeer 137
 
34690 amit.gupta 138
	/**
139
	 * Configure Hibernate properties
140
	 */
24433 amit.gupta 141
	@Bean
23723 amit.gupta 142
	public Properties getHibernateProperties() {
143
		Properties dbProperties = new Properties();
144
		dbProperties.put(HIBERNATE_DIALECT, hibernateDialect);
145
		dbProperties.put(HIBERNATE_SHOW_SQL, hibernateShowSql);
146
		dbProperties.put(HIBERNATE_FORMAT_SQL, hibernateFormatSql);
147
		dbProperties.put(HIBERNATE_JDBC_BATCH_SIZE, hibernateBatchSize);
35828 amit 148
		dbProperties.put("hibernate.order_inserts", hibernateOrderInserts);
149
		dbProperties.put("hibernate.order_updates", hibernateOrderUpdates);
23723 amit.gupta 150
		return dbProperties;
151
	}
25721 tejbeer 152
 
34690 amit.gupta 153
	/**
154
	 * Configure Hibernate SessionFactory
155
	 */
23898 amit.gupta 156
	@Primary
34690 amit.gupta 157
	@Bean(name = "sessionFactory")
23723 amit.gupta 158
	@Autowired
159
	public SessionFactory getSessionFactory(DataSource dataSource) {
160
		LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
161
		sessionBuilder.addProperties(getHibernateProperties());
162
		sessionBuilder.scanPackages("com.spice.profitmandi.dao.*");
34690 amit.gupta 163
		LOGGER.info("SessionFactory created");
23723 amit.gupta 164
		return sessionBuilder.buildSessionFactory();
165
	}
25721 tejbeer 166
 
34690 amit.gupta 167
	/**
168
	 * Transaction Manager
169
	 */
23898 amit.gupta 170
	@Primary
34690 amit.gupta 171
	@Bean(name = "transactionManager")
23723 amit.gupta 172
	@Autowired
173
	public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
174
		HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
34690 amit.gupta 175
		LOGGER.info("TransactionManager created");
23723 amit.gupta 176
		return transactionManager;
177
	}
25721 tejbeer 178
 
34690 amit.gupta 179
	/**
180
	 * ObjectMapper Bean with Java 8 Time module config
181
	 */
23738 amit.gupta 182
	@Bean
34690 amit.gupta 183
	public ObjectMapper objectMapper() {
184
		DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
185
				.parseCaseInsensitive()
186
				.append(DateTimeFormatter.ISO_LOCAL_DATE)
187
				.optionalStart().appendLiteral('T').optionalEnd()
188
				.appendLiteral(' ')
189
				.append(DateTimeFormatter.ISO_LOCAL_TIME)
190
				.toFormatter();
191
 
192
		DateTimeFormatter standardFormatter = new DateTimeFormatterBuilder()
193
				.parseCaseInsensitive()
194
				.append(DateTimeFormatter.ISO_LOCAL_DATE)
195
				.appendLiteral('T')
196
				.append(DateTimeFormatter.ISO_LOCAL_TIME)
197
				.toFormatter();
198
 
199
		JavaTimeModule javaTimeModule = new JavaTimeModule();
200
		javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(standardFormatter));
201
		javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
202
		javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
203
		javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
204
 
205
		ObjectMapper mapper = new ObjectMapper()
206
				.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
207
				.registerModule(new ParameterNamesModule())
208
				.registerModule(new Jdk8Module())
209
				.registerModule(javaTimeModule);
210
 
211
		LOGGER.info("ObjectMapper configured");
212
		return mapper;
213
	}
214
 
215
	/**
216
	 * Mongo Client Bean
217
	 */
35393 amit 218
	@Bean(destroyMethod = "close")
23738 amit.gupta 219
	public Mongo mongoClient(SessionFactory sessionFactory) {
220
		return new Mongo(mongoHost, contentMongoHost);
221
	}
25721 tejbeer 222
 
34690 amit.gupta 223
	/**
224
	 * Gson Bean for LocalDate and LocalDateTime
225
	 */
25721 tejbeer 226
	@Bean(name = "gson")
227
	public Gson gson() {
34690 amit.gupta 228
		Gson gson = new GsonBuilder()
229
				.serializeNulls()
29838 tejbeer 230
				.registerTypeAdapter(LocalDate.class, new LocalDateJsonConverter())
34690 amit.gupta 231
				.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeJsonConverter())
232
				.create();
233
		LOGGER.info("Gson configured");
25721 tejbeer 234
		return gson;
235
	}
35393 amit 236
 
237
	/**
238
	 * Cleanup method to prevent memory leaks on shutdown.
239
	 * Deregisters JDBC drivers and stops MySQL cleanup thread.
240
	 */
241
	@PreDestroy
242
	public void cleanup() {
243
		LOGGER.info("DBConfig cleanup started...");
244
 
245
		// Stop MySQL AbandonedConnectionCleanupThread
246
		try {
247
			AbandonedConnectionCleanupThread.checkedShutdown();
248
			LOGGER.info("MySQL AbandonedConnectionCleanupThread stopped");
249
		} catch (Exception e) {
250
			LOGGER.error("Error stopping MySQL cleanup thread", e);
251
		}
252
 
253
		// Deregister JDBC drivers loaded by this webapp's classloader
254
		ClassLoader cl = Thread.currentThread().getContextClassLoader();
255
		Enumeration<Driver> drivers = DriverManager.getDrivers();
256
		while (drivers.hasMoreElements()) {
257
			Driver driver = drivers.nextElement();
258
			if (driver.getClass().getClassLoader() == cl) {
259
				try {
260
					DriverManager.deregisterDriver(driver);
261
					LOGGER.info("Deregistered JDBC driver: {}", driver);
262
				} catch (SQLException e) {
263
					LOGGER.error("Error deregistering JDBC driver {}", driver, e);
264
				}
265
			}
266
		}
267
 
268
		LOGGER.info("DBConfig cleanup completed");
269
	}
23723 amit.gupta 270
}