From cd99d57cccb88ea8a058eca530d62a81a665983c Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 11 Apr 2013 10:13:44 +0200 Subject: o Initial import. --- src/main/java/io/trygvis/Main.java | 62 ++++++ src/main/java/io/trygvis/MyJob.java | 38 ++++ src/main/java/io/trygvis/data/QueueRepository.java | 8 + src/main/java/io/trygvis/data/TaskRepository.java | 7 + src/main/java/io/trygvis/model/Article.java | 57 +++++ src/main/java/io/trygvis/model/Queue.java | 46 ++++ src/main/java/io/trygvis/model/Task.java | 32 +++ src/main/java/io/trygvis/queue/AsyncService.java | 18 ++ .../java/io/trygvis/queue/JpaAsyncService.java | 246 +++++++++++++++++++++ src/main/java/io/trygvis/spring/Config.java | 174 +++++++++++++++ src/main/resources/applicationContext.xml | 22 ++ src/main/resources/logback.xml | 28 +++ 12 files changed, 738 insertions(+) create mode 100755 src/main/java/io/trygvis/Main.java create mode 100755 src/main/java/io/trygvis/MyJob.java create mode 100755 src/main/java/io/trygvis/data/QueueRepository.java create mode 100755 src/main/java/io/trygvis/data/TaskRepository.java create mode 100755 src/main/java/io/trygvis/model/Article.java create mode 100755 src/main/java/io/trygvis/model/Queue.java create mode 100755 src/main/java/io/trygvis/model/Task.java create mode 100755 src/main/java/io/trygvis/queue/AsyncService.java create mode 100755 src/main/java/io/trygvis/queue/JpaAsyncService.java create mode 100755 src/main/java/io/trygvis/spring/Config.java create mode 100755 src/main/resources/applicationContext.xml create mode 100755 src/main/resources/logback.xml (limited to 'src') diff --git a/src/main/java/io/trygvis/Main.java b/src/main/java/io/trygvis/Main.java new file mode 100755 index 0000000..19167d7 --- /dev/null +++ b/src/main/java/io/trygvis/Main.java @@ -0,0 +1,62 @@ +package io.trygvis; + +import io.trygvis.queue.*; +import org.hibernate.dialect.*; +import org.slf4j.*; +import org.slf4j.bridge.*; +import org.springframework.beans.factory.annotation.*; +import org.springframework.context.support.*; +import org.springframework.stereotype.*; +import org.springframework.transaction.annotation.*; + +import static java.lang.System.*; + +@Component +@Transactional +public class Main { + private static final Logger log = LoggerFactory.getLogger(Main.class); + + public static void main(String[] args) throws Exception { + SLF4JBridgeHandler.install(); + + String username = getProperty("user.name"); + setProperty("database.url", getProperty("jdbc.url", "jdbc:postgresql://localhost/" + username)); + setProperty("database.username", username); + setProperty("database.password", username); + setProperty("hibernate.showSql", "true"); + setProperty("hibernate.hbm2ddl.auto", "create"); // create + setProperty("hibernate.dialect", PostgreSQL82Dialect.class.getName()); + + log.info("Starting context"); + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); + context.start(); + log.info("Started context"); + + try { + context.getBean(Main.class).run(); + log.info("Sleeping"); + Thread.sleep(1000 * 1000); + } catch (Exception e) { + e.printStackTrace(System.out); + } + + log.info("Stopping context"); + context.stop(); + log.info("Stopped context"); + + exit(0); + } + + @Autowired + private AsyncService asyncService; + + public void run() throws Exception { + log.info("Main.run"); + + asyncService.registerQueue("test-queue", 1, MyJob.class); + + AsyncService.QueueRef queue = asyncService.getQueue("test-queue"); + + AsyncService.ExecutionRef executionRef = asyncService.schedule(queue); + } +} diff --git a/src/main/java/io/trygvis/MyJob.java b/src/main/java/io/trygvis/MyJob.java new file mode 100755 index 0000000..7303a33 --- /dev/null +++ b/src/main/java/io/trygvis/MyJob.java @@ -0,0 +1,38 @@ +package io.trygvis; + +import io.trygvis.model.*; +import org.quartz.*; +import org.slf4j.*; + +import java.util.*; +import javax.persistence.*; + +public class MyJob implements Job { + private final Logger log = LoggerFactory.getLogger(getClass()); + + @PersistenceContext + private EntityManager entityManager; + + public void execute(JobExecutionContext context) throws JobExecutionException { + log.info("MyJob.execute: BEGIN"); + log.info("entityManager = {}", entityManager); + log.info("context.getJobDetail().getKey() = {}", context.getJobDetail().getKey()); + +/* + Date now = new Date(); + + log.info("now = {}", now); + +// Article article = entityManager.find(Article.class, 1); +// +// System.out.println("article = " + article); +// article.setUpdated(now); +// entityManager.persist(article); + + Article article = new Article(new Date(), null, "title", "body"); + entityManager.persist(article); +*/ + + log.info("MyJob.execute: END"); + } +} diff --git a/src/main/java/io/trygvis/data/QueueRepository.java b/src/main/java/io/trygvis/data/QueueRepository.java new file mode 100755 index 0000000..143d747 --- /dev/null +++ b/src/main/java/io/trygvis/data/QueueRepository.java @@ -0,0 +1,8 @@ +package io.trygvis.data; + +import io.trygvis.model.*; +import org.springframework.data.jpa.repository.*; + +public interface QueueRepository extends JpaRepository { + Queue findByName(String name); +} diff --git a/src/main/java/io/trygvis/data/TaskRepository.java b/src/main/java/io/trygvis/data/TaskRepository.java new file mode 100755 index 0000000..0b65199 --- /dev/null +++ b/src/main/java/io/trygvis/data/TaskRepository.java @@ -0,0 +1,7 @@ +package io.trygvis.data; + +import io.trygvis.model.*; +import org.springframework.data.jpa.repository.*; + +public interface TaskRepository extends JpaRepository { +} diff --git a/src/main/java/io/trygvis/model/Article.java b/src/main/java/io/trygvis/model/Article.java new file mode 100755 index 0000000..6383e50 --- /dev/null +++ b/src/main/java/io/trygvis/model/Article.java @@ -0,0 +1,57 @@ +package io.trygvis.model; + +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Entity +public class Article { + @Id + @SequenceGenerator(name="id_seq", sequenceName="id_seq") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_seq") + private Integer id; + private Date created; + private Date updated; + private String title; + private String body; + + @SuppressWarnings("UnusedDeclaration") + private Article() { + } + + public Article(Date created, Date updated, String title, String body) { + this.created = created; + this.updated = updated; + this.title = title; + this.body = body; + } + + public Integer getId() { + return id; + } + + public Date getCreated() { + return created; + } + + public Date getUpdated() { + return updated; + } + + public void setUpdated(Date updated) { + this.updated = updated; + } + + public String getTitle() { + return title; + } + + public String getBody() { + return body; + } +} diff --git a/src/main/java/io/trygvis/model/Queue.java b/src/main/java/io/trygvis/model/Queue.java new file mode 100755 index 0000000..52c5c0f --- /dev/null +++ b/src/main/java/io/trygvis/model/Queue.java @@ -0,0 +1,46 @@ +package io.trygvis.model; + +import javax.persistence.*; + +@Entity +@Table( + uniqueConstraints = { + @UniqueConstraint(name = "uq_queue__name", columnNames = "name") + } +) +public class Queue { + + @Id + @SequenceGenerator(name = "queue_seq", sequenceName = "queue_seq") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "queue_seq") + private Integer id; + + private String name; + + private long interval; + + public Queue(String name, long interval) { + this.name = name; + this.interval = interval; + } + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getInterval() { + return interval; + } + + public void setInterval(long interval) { + this.interval = interval; + } +} diff --git a/src/main/java/io/trygvis/model/Task.java b/src/main/java/io/trygvis/model/Task.java new file mode 100755 index 0000000..fa44e26 --- /dev/null +++ b/src/main/java/io/trygvis/model/Task.java @@ -0,0 +1,32 @@ +package io.trygvis.model; + +import javax.persistence.*; + +@Entity +public class Task { + @Id + @SequenceGenerator(name = "task_seq", sequenceName = "task_seq") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "task_seq") + private Integer id; + + @ManyToOne + private Queue queue; + + private Long long1; + + public Task(Queue queue) { + this.queue = queue; + } + + public Integer getId() { + return id; + } + + public Long getLong1() { + return long1; + } + + public void setLong1(Long long1) { + this.long1 = long1; + } +} diff --git a/src/main/java/io/trygvis/queue/AsyncService.java b/src/main/java/io/trygvis/queue/AsyncService.java new file mode 100755 index 0000000..dcbe991 --- /dev/null +++ b/src/main/java/io/trygvis/queue/AsyncService.java @@ -0,0 +1,18 @@ +package io.trygvis.queue; + +import org.quartz.*; + +public interface AsyncService { + + void registerQueue(String name, int interval, Class klass) throws SchedulerException; + + QueueRef getQueue(String name); + + ExecutionRef schedule(QueueRef queue); + + interface QueueRef { + } + + interface ExecutionRef { + } +} diff --git a/src/main/java/io/trygvis/queue/JpaAsyncService.java b/src/main/java/io/trygvis/queue/JpaAsyncService.java new file mode 100755 index 0000000..2d6c2df --- /dev/null +++ b/src/main/java/io/trygvis/queue/JpaAsyncService.java @@ -0,0 +1,246 @@ +package io.trygvis.queue; + +import io.trygvis.data.QueueRepository; +import io.trygvis.data.TaskRepository; +import io.trygvis.model.Queue; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.JobKey; +import org.quartz.JobPersistenceException; +import org.quartz.Scheduler; +import org.quartz.SchedulerContext; +import org.quartz.SchedulerException; +import org.quartz.SchedulerFactory; +import org.quartz.SimpleScheduleBuilder; +import org.quartz.SimpleTrigger; +import org.quartz.TriggerBuilder; +import org.quartz.impl.DirectSchedulerFactory; +import org.quartz.impl.JobDetailImpl; +import org.quartz.impl.StdSchedulerFactory; +import org.quartz.impl.jdbcjobstore.JobStoreSupport; +import org.quartz.impl.jdbcjobstore.JobStoreTX; +import org.quartz.impl.jdbcjobstore.PostgreSQLDelegate; +import org.quartz.spi.JobStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import javax.annotation.PostConstruct; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.RollbackException; +import javax.persistence.TypedQuery; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; + +import static org.quartz.SimpleScheduleBuilder.simpleSchedule; + +@SuppressWarnings("SpringJavaAutowiringInspection") +@Component +public class JpaAsyncService implements AsyncService { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private DataSource dataSource; + + private static DataSource dataSourceStatic; + + @Autowired + private PlatformTransactionManager transactionManager; + + private static PlatformTransactionManager transactionManagerStatic; + + @Autowired + private QueueRepository queueRepository; + + @Autowired + private TaskRepository taskRepository; + + private Scheduler scheduler; + + @PostConstruct + public void afterPropertiesSet() throws Exception { + transactionManagerStatic = transactionManager; + dataSourceStatic = dataSource; + log.info("afterPropertiesSet!!"); + Properties quartzProperties = new Properties(); + quartzProperties.setProperty(StdSchedulerFactory.PROP_JOB_STORE_CLASS, JobStoreTX.class.getName()); + quartzProperties.setProperty(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, "queue"); + quartzProperties.setProperty(StdSchedulerFactory.PROP_SCHED_SKIP_UPDATE_CHECK, "true"); + quartzProperties.setProperty(StdSchedulerFactory.PROP_SCHED_SKIP_UPDATE_CHECK, "true"); +// quartzProperties.setProperty(StdSchedulerFactory.PROP_DATASOURCE_PREFIX, "wat"); + quartzProperties.setProperty(StdSchedulerFactory.PROP_JOB_STORE_CLASS, JpaDataSourceJobStore.class.getName()); + quartzProperties.setProperty("org.quartz.threadPool.threadCount", "10"); + quartzProperties.setProperty("org.quartz.jobStore.driverDelegateClass", PostgreSQLDelegate.class.getName()); + quartzProperties.setProperty("org.quartz.scheduler.jmx.export", "true"); + SchedulerFactory schedulerFactory = new StdSchedulerFactory(quartzProperties); + + Scheduler s = schedulerFactory.getScheduler(); + System.out.println("s.getSchedulerName() = " + s.getSchedulerName()); + scheduler = schedulerFactory.getScheduler("queue"); + } + + @Transactional + public void registerQueue(String name, int interval, Class klass) throws SchedulerException { + + Queue q = queueRepository.findByName(name); + + if (q == null) { + Queue queue = new Queue(name, interval); + queueRepository.save(queue); + } else { + boolean dirty = false; + if (interval != q.getInterval()) { + q.setInterval(interval); + dirty = true; + } + + if (dirty) { + queueRepository.save(q); + } + } + + JobDetailImpl jobDetail = new JobDetailImpl(); + JobKey jobKey = JobKey.jobKey("queue-" + name); + + jobDetail.setKey(jobKey); + jobDetail.setJobClass(AsyncServiceJob.class); + jobDetail.setDurability(true); + JobDataMap map = new JobDataMap(); + map.put("class", klass.getName()); + jobDetail.setJobDataMap(map); + + scheduler.addJob(jobDetail, true); + + SimpleScheduleBuilder schedule = simpleSchedule(). + repeatForever(). + withIntervalInSeconds(interval); + + SimpleTrigger trigger = TriggerBuilder.newTrigger(). + withSchedule(schedule). + withIdentity(jobKey.getName()). + forJob(jobKey). + build(); + + scheduler.scheduleJob(trigger); + } + + @Transactional(readOnly = true) + public JpaQueueRef getQueue(String name) { + TypedQuery query = entityManager.createQuery("select q from io.trygvis.model.Queue q where name = ?1", Queue.class); + query.setParameter(1, name); + List list = query.getResultList(); + System.out.println("list.size() = " + list.size()); + + if (list.size() == 0) { + throw new RollbackException("No such queue: '" + name + "'."); + } + + Queue queue = list.get(0); + + entityManager.detach(query); + + return new JpaQueueRef(queue); + } + + @Transactional + public JpaExecutionRef schedule(JpaQueueRef queue) { + return null; + } + + static class JpaQueueRef implements AsyncService.QueueRef { + public final Queue queue; + + JpaQueueRef(Queue queue) { + this.queue = queue; + } + } + + static class JpaExecutionRef implements AsyncService.ExecutionRef { + } + + public static class AsyncServiceJob implements Job { + private final Logger log = LoggerFactory.getLogger(getClass()); + + public void execute(JobExecutionContext context) throws JobExecutionException { + try { + log.info("Running"); + + SchedulerContext map = context.getScheduler().getContext(); + ApplicationContext applicationContext = (ApplicationContext) map.get("applicationContext"); + + log.info("applicationContext = {}", applicationContext); + + String className = map.getString("class"); + + log.info("className = {}", className); + + Class klass = getClass().getClassLoader().loadClass(className); + Object bean = applicationContext.getBean(klass); + + log.info("bean = {}", bean); + } catch (Exception e) { + log.warn("fail", e); + throw new JobExecutionException(e, false); + } + } + } + + public static class JpaDataSourceJobStore extends JobStoreSupport { + + public JpaDataSourceJobStore() { + setDataSource("wat"); + } + + protected Connection getNonManagedTXConnection() throws JobPersistenceException { +// DefaultTransactionDefinition definition = new DefaultTransactionDefinition(); +// definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); +// TransactionStatus transaction = transactionManagerStatic.getTransaction(definition); + + System.out.println("dataSourceStatic = " + dataSourceStatic); + Connection c = DataSourceUtils.getConnection(dataSourceStatic); + try { + c.setAutoCommit(false); + } catch (SQLException e) { + throw new RuntimeException(e); + } + System.out.println("c = " + c); + + return c; + } + + protected void closeConnection(Connection c) { + try { + DataSourceUtils.doCloseConnection(c, dataSourceStatic); + } catch (SQLException e) { + e.printStackTrace(); + } + + } + + protected Object executeInLock(String lockName, TransactionCallback txCallback) throws JobPersistenceException { + return executeInNonManagedTXLock(lockName, txCallback); + } + } +} diff --git a/src/main/java/io/trygvis/spring/Config.java b/src/main/java/io/trygvis/spring/Config.java new file mode 100755 index 0000000..9a968e0 --- /dev/null +++ b/src/main/java/io/trygvis/spring/Config.java @@ -0,0 +1,174 @@ +package io.trygvis.spring; + +import com.jolbox.bonecp.*; +import io.trygvis.MyJob; +import io.trygvis.model.*; +import org.hibernate.*; +import org.hibernate.annotations.*; +import org.hibernate.cfg.*; +import org.hibernate.ejb.*; +import org.quartz.*; +import org.quartz.impl.jdbcjobstore.*; +import org.quartz.spi.*; +import org.springframework.beans.factory.annotation.*; +import org.springframework.context.annotation.*; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.*; +import org.springframework.data.jpa.repository.config.*; +import org.springframework.jdbc.datasource.*; +import org.springframework.orm.hibernate4.*; +import org.springframework.orm.jpa.*; +import org.springframework.scheduling.quartz.*; +import org.springframework.transaction.*; +import org.springframework.transaction.annotation.*; +import org.springframework.transaction.support.*; + +import java.util.*; +import javax.persistence.*; +import javax.sql.*; + +import static org.hibernate.cfg.AvailableSettings.*; +import static org.hibernate.ejb.AvailableSettings.*; + +@Configuration +@ComponentScan(basePackages = "io.trygvis") +@EnableTransactionManagement +@EnableJpaRepositories(basePackages = "io.trygvis.data") +public class Config { + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws Exception { + return new PropertySourcesPlaceholderConfigurer() {{ +// setLocation(new UrlResource("file:environment.properties")); + setProperties(System.getProperties()); + setLocalOverride(true); + }}; + } + +// public SpringBeanJobFactory springBeanJobFactory() { +// SpringBeanJobFactory factory = new SpringBeanJobFactory(); +// return factory; +// } + +/* + @Bean + public SchedulerFactoryBean quartz(DataSource dataSource, PlatformTransactionManager transactionManager) { + SchedulerFactoryBean bean = new SchedulerFactoryBean(); + bean.setApplicationContextSchedulerContextKey("applicationContext"); + bean.setDataSource(dataSource); + bean.setTransactionManager(transactionManager); +// bean.setJobFactory(new JobFactory() { +// public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException { +// Class klass = bundle.getJobDetail().getJobClass(); +// } +// }); + + Properties quartzProperties = new Properties(); + quartzProperties.setProperty("org.quartz.scheduler.skipUpdateCheck", "true"); +// quartzProperties.setProperty("org.quartz.jobStore.selectWithLockSQL", "false"); + quartzProperties.setProperty("org.quartz.jobStore.driverDelegateClass", PostgreSQLDelegate.class.getName()); + quartzProperties.setProperty("org.quartz.scheduler.jmx.export", "true"); + bean.setQuartzProperties(quartzProperties); + return bean; + } +*/ + + // This turns out to be fairly useless as Spring won't register them automatically. + // It's probably better to use @Scheduled/@Async instead + /* + @Bean(name = "my-job") + public JobDetailFactoryBean myJobDetailBean() { + JobDetailFactoryBean bean = new JobDetailFactoryBean(); + bean.setJobClass(MyJob.class); + bean.setDurability(true); + + return bean; + } + + @Bean + public CronTriggerFactoryBean myJobTrigger(JobDetail jobDetail) { + CronTriggerFactoryBean bean = new CronTriggerFactoryBean(); + bean.setName("my-trigger"); + bean.setBeanName("my-job"); + bean.setJobDetail(jobDetail); + bean.setCronExpression("0/10 * * * * ?"); + + return bean; + } + */ + + @Bean + public DataSource dataSource(@Value("${database.url}") String jdbcUrl, + @Value("${database.username}") String username, + @Value("${database.password}") String password) { + BoneCPDataSource ds = new BoneCPDataSource(); + + ds.setLogStatementsEnabled(true); + + ds.setJdbcUrl(jdbcUrl); + ds.setUsername(username); + ds.setPassword(password); + + ds.setIdleConnectionTestPeriodInSeconds(60); + ds.setIdleMaxAgeInSeconds(240); + ds.setMaxConnectionsPerPartition(40); + ds.setMinConnectionsPerPartition(0); + ds.setPartitionCount(1); + ds.setAcquireIncrement(1); + ds.setStatementsCacheSize(1000); + ds.setReleaseHelperThreads(3); + ds.setStatisticsEnabled(true); + return new TransactionAwareDataSourceProxy(new LazyConnectionDataSourceProxy(ds)); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, + @Value("${hibernate.hbm2ddl.auto}") String hbm2ddl, + @Value("${hibernate.showSql}") boolean showSql, + @Value("${hibernate.dialect}") String dialect) { + LocalContainerEntityManagerFactoryBean x = new LocalContainerEntityManagerFactoryBean(); + x.setDataSource(dataSource); + x.setJpaPropertyMap(createJpaMap(hbm2ddl, showSql, dialect)); + x.setPackagesToScan(Article.class.getPackage().getName()); + HibernatePersistence persistenceProvider = new HibernatePersistence(); + x.setPersistenceProvider(persistenceProvider); + return x; + } + + public static Map createJpaMap(String hbm2ddl, boolean showSql, String dialect) { + Map map = new HashMap<>(); + map.put(HBM2DDL_AUTO, hbm2ddl); + map.put(FORMAT_SQL, showSql); + map.put(SHOW_SQL, showSql); + map.put(USE_SQL_COMMENTS, showSql); + map.put(GENERATE_STATISTICS, true); + map.put(NAMING_STRATEGY, ImprovedNamingStrategy.class.getName()); + + map.put(DEFAULT_CACHE_CONCURRENCY_STRATEGY, CacheConcurrencyStrategy.READ_WRITE.toString()); + map.put(CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName()); +// map.put(CACHE_REGION_FACTORY, EhCacheRegionFactory.class.getName()); + map.put(USE_SECOND_LEVEL_CACHE, false); + map.put(USE_QUERY_CACHE, false); +// map.put(SHARED_CACHE_MODE, SharedCacheMode.ENABLE_SELECTIVE.toString()); + + map.put(DIALECT, dialect); + map.put("hibernate.temp.use_jdbc_metadata_defaults", "false"); + + return map; + } + + @Bean + public SessionFactory sessionFactory(LocalContainerEntityManagerFactoryBean entityManagerFactory) { + return ((HibernateEntityManagerFactory) entityManagerFactory.nativeEntityManagerFactory).getSessionFactory(); + } + + @Bean + public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + return new JpaTransactionManager(entityManagerFactory); + } + + @Bean + public TransactionTemplate transactionTemplate(PlatformTransactionManager platformTransactionManager) { + return new TransactionTemplate(platformTransactionManager); + } +} diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml new file mode 100755 index 0000000..9856a0b --- /dev/null +++ b/src/main/resources/applicationContext.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100755 index 0000000..038a2f1 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + -- cgit v1.2.3