Subversion Repositories SmartDukaan

Rev

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