001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.camel.processor.idempotent.jpa; 019 020 import org.apache.camel.processor.idempotent.MessageIdRepository; 021 import org.springframework.orm.jpa.JpaCallback; 022 import org.springframework.orm.jpa.JpaTemplate; 023 import org.springframework.orm.jpa.JpaTransactionManager; 024 import org.springframework.transaction.TransactionDefinition; 025 import org.springframework.transaction.TransactionStatus; 026 import org.springframework.transaction.support.TransactionCallback; 027 import org.springframework.transaction.support.TransactionTemplate; 028 029 import javax.persistence.EntityManager; 030 import javax.persistence.EntityManagerFactory; 031 import javax.persistence.Persistence; 032 import javax.persistence.PersistenceException; 033 034 import java.util.List; 035 036 /** 037 * @version $Revision: 1.1 $ 038 */ 039 public class JpaMessageIdRepository implements MessageIdRepository { 040 protected static final String QUERY_STRING = "select x from " + MessageProcessed.class.getName() + " x where x.processorName = ?1 and x.messageId = ?2"; 041 private JpaTemplate jpaTemplate; 042 private String processorName; 043 private TransactionTemplate transactionTemplate; 044 045 public static JpaMessageIdRepository jpaMessageIdRepository(String persistenceUnit, String processorName) { 046 EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit); 047 return jpaMessageIdRepository(new JpaTemplate(entityManagerFactory), processorName); 048 } 049 050 public static JpaMessageIdRepository jpaMessageIdRepository(JpaTemplate jpaTemplate, String processorName) { 051 return new JpaMessageIdRepository(jpaTemplate, processorName); 052 } 053 054 public JpaMessageIdRepository(JpaTemplate template, String processorName) { 055 this(template, createTransactionTemplate(template), processorName); 056 } 057 058 public JpaMessageIdRepository(JpaTemplate template, TransactionTemplate transactionTemplate, String processorName) { 059 this.jpaTemplate = template; 060 this.processorName = processorName; 061 this.transactionTemplate=transactionTemplate; 062 } 063 064 static private TransactionTemplate createTransactionTemplate(JpaTemplate jpaTemplate) { 065 TransactionTemplate transactionTemplate = new TransactionTemplate(); 066 transactionTemplate.setTransactionManager(new JpaTransactionManager(jpaTemplate.getEntityManagerFactory())); 067 transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 068 return transactionTemplate; 069 } 070 071 public boolean contains(final String messageId) { 072 // Run this in single transaction. 073 Boolean rc = (Boolean) transactionTemplate.execute(new TransactionCallback(){ 074 public Object doInTransaction(TransactionStatus arg0) { 075 076 List list = jpaTemplate.find(QUERY_STRING, processorName, messageId); 077 if (list.isEmpty()) { 078 MessageProcessed processed = new MessageProcessed(); 079 processed.setProcessorName(processorName); 080 processed.setMessageId(messageId); 081 jpaTemplate.persist(processed); 082 jpaTemplate.flush(); 083 return Boolean.FALSE; 084 } 085 else { 086 return Boolean.TRUE; 087 } 088 } 089 }); 090 return rc.booleanValue(); 091 } 092 }