aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2013-04-11 10:13:44 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2013-04-11 10:13:44 +0200
commitcd99d57cccb88ea8a058eca530d62a81a665983c (patch)
tree80d8724872f757876da0fc8dccd409dd5693f19c
downloadquartz-based-queue-cd99d57cccb88ea8a058eca530d62a81a665983c.tar.gz
quartz-based-queue-cd99d57cccb88ea8a058eca530d62a81a665983c.tar.bz2
quartz-based-queue-cd99d57cccb88ea8a058eca530d62a81a665983c.tar.xz
quartz-based-queue-cd99d57cccb88ea8a058eca530d62a81a665983c.zip
o Initial import.
-rw-r--r--.gitignore3
-rwxr-xr-xpom.xml109
-rwxr-xr-xsrc/main/java/io/trygvis/Main.java62
-rwxr-xr-xsrc/main/java/io/trygvis/MyJob.java38
-rwxr-xr-xsrc/main/java/io/trygvis/data/QueueRepository.java8
-rwxr-xr-xsrc/main/java/io/trygvis/data/TaskRepository.java7
-rwxr-xr-xsrc/main/java/io/trygvis/model/Article.java57
-rwxr-xr-xsrc/main/java/io/trygvis/model/Queue.java46
-rwxr-xr-xsrc/main/java/io/trygvis/model/Task.java32
-rwxr-xr-xsrc/main/java/io/trygvis/queue/AsyncService.java18
-rwxr-xr-xsrc/main/java/io/trygvis/queue/JpaAsyncService.java246
-rwxr-xr-xsrc/main/java/io/trygvis/spring/Config.java174
-rwxr-xr-xsrc/main/resources/applicationContext.xml22
-rwxr-xr-xsrc/main/resources/logback.xml28
14 files changed, 850 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f83e8cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.idea
+target
+*.iml
diff --git a/pom.xml b/pom.xml
new file mode 100755
index 0000000..d53bbc1
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,109 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.trygvis.2013.04</groupId>
+ <artifactId>quartz-based-queue</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-jpamodelgen</artifactId>
+ <version>1.2.0.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>4.1.9.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>4.1.9.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>3.2.2.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>3.2.2.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ <version>3.2.2.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.data</groupId>
+ <artifactId>spring-data-jpa</artifactId>
+ <version>1.2.0.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>com.jolbox</groupId>
+ <artifactId>bonecp-spring</artifactId>
+ <version>0.7.1.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <version>2.1.7</version>
+ <exclusions>
+ <exclusion>
+ <groupId>c3p0</groupId>
+ <artifactId>c3p0</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>14.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jul-to-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>9.2-1002-jdbc4</version>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
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.QueueRef, AsyncService.ExecutionRef> 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, Long> {
+ 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<Task, Long> {
+}
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<QueueRef extends AsyncService.QueueRef, ExecutionRef extends AsyncService.ExecutionRef> {
+
+ 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<JpaAsyncService.JpaQueueRef, JpaAsyncService.JpaExecutionRef> {
+
+ 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<Queue> query = entityManager.createQuery("select q from io.trygvis.model.Queue q where name = ?1", Queue.class);
+ query.setParameter(1, name);
+ List<Queue> 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<? extends Job> 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<String, Object> createJpaMap(String hbm2ddl, boolean showSql, String dialect) {
+ Map<String, Object> 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 @@
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://www.springframework.org/schema/beans"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:jdbc="http://www.springframework.org/schema/jdbc"
+ xmlns:jee="http://www.springframework.org/schema/jee"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:jpa="http://www.springframework.org/schema/data/jpa"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
+ http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
+ http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
+ http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
+ http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
+
+ <context:annotation-config/>
+ <bean class="io.trygvis.spring.Config"/>
+
+</beans>
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 @@
+<configuration debug="false">
+
+ <logger name="io.trygvis" level="DEBUG"/>
+<!--
+ <logger name="org.springframework" level="INFO"/>
+-->
+ <logger name="org.springframework" level="INFO"/>
+ <logger name="org.springframework.scheduling" level="DEBUG"/>
+ <logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>
+ <logger name="org.hibernate" level="DEBUG"/>
+ <logger name="org.quartz" level="DEBUG"/>
+<!--
+ <logger name="org" level="INFO"/>
+ <logger name="net" level="INFO"/>
+ <logger name="com" level="INFO"/>
+-->
+ <logger name="com.jolbox" level="DEBUG"/>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="DEBUG">
+ <appender-ref ref="STDOUT"/>
+ </root>
+</configuration>