Rename modules {org.springframework.*=>spring-*}
This renaming more intuitively expresses the relationship between
subprojects and the JAR artifacts they produce.
Tracking history across these renames is possible, but it requires
use of the --follow flag to `git log`, for example
$ git log spring-aop/src/main/java/org/springframework/aop/Advisor.java
will show history up until the renaming event, where
$ git log --follow spring-aop/src/main/java/org/springframework/aop/Advisor.java
will show history for all changes to the file, before and after the
renaming.
See http://chrisbeams.com/git-diff-across-renamed-directories
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import org.springframework.core.enums.ShortCodedLabeledEnum;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
public class Colour extends ShortCodedLabeledEnum {
|
||||
|
||||
public static final Colour RED = new Colour(0, "RED");
|
||||
public static final Colour BLUE = new Colour(1, "BLUE");
|
||||
public static final Colour GREEN = new Colour(2, "GREEN");
|
||||
public static final Colour PURPLE = new Colour(3, "PURPLE");
|
||||
|
||||
private Colour(int code, String label) {
|
||||
super(code, label);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 21.08.2003
|
||||
*/
|
||||
public class DerivedTestBean extends TestBean implements Serializable, BeanNameAware, DisposableBean {
|
||||
|
||||
private String beanName;
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
private boolean destroyed;
|
||||
|
||||
|
||||
public DerivedTestBean() {
|
||||
}
|
||||
|
||||
public DerivedTestBean(String[] names) {
|
||||
if (names == null || names.length < 2) {
|
||||
throw new IllegalArgumentException("Invalid names array");
|
||||
}
|
||||
setName(names[0]);
|
||||
setBeanName(names[1]);
|
||||
}
|
||||
|
||||
public static DerivedTestBean create(String[] names) {
|
||||
return new DerivedTestBean(names);
|
||||
}
|
||||
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
if (this.beanName == null || beanName == null) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
}
|
||||
|
||||
public String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
public void setSpouseRef(String name) {
|
||||
setSpouse(new TestBean(name));
|
||||
}
|
||||
|
||||
|
||||
public void initialize() {
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
public boolean wasInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
this.destroyed = true;
|
||||
}
|
||||
|
||||
public boolean wasDestroyed() {
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
public interface INestedTestBean {
|
||||
|
||||
public String getCompany();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
public interface IOther {
|
||||
|
||||
void absquatulate();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Interface used for {@link org.springframework.beans.TestBean}.
|
||||
*
|
||||
* <p>Two methods are the same as on Person, but if this
|
||||
* extends person it breaks quite a few tests..
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface ITestBean {
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
|
||||
ITestBean getSpouse();
|
||||
|
||||
void setSpouse(ITestBean spouse);
|
||||
|
||||
ITestBean[] getSpouses();
|
||||
|
||||
String[] getStringArray();
|
||||
|
||||
void setStringArray(String[] stringArray);
|
||||
|
||||
/**
|
||||
* Throws a given (non-null) exception.
|
||||
*/
|
||||
void exceptional(Throwable t) throws Throwable;
|
||||
|
||||
Object returnsThis();
|
||||
|
||||
INestedTestBean getDoctor();
|
||||
|
||||
INestedTestBean getLawyer();
|
||||
|
||||
IndexedTestBean getNestedIndexedBean();
|
||||
|
||||
/**
|
||||
* Increment the age by one.
|
||||
* @return the previous age
|
||||
*/
|
||||
int haveBirthday();
|
||||
|
||||
void unreliableFileOperation() throws IOException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 11.11.2003
|
||||
*/
|
||||
public class IndexedTestBean {
|
||||
|
||||
private TestBean[] array;
|
||||
|
||||
private Collection collection;
|
||||
|
||||
private List list;
|
||||
|
||||
private Set set;
|
||||
|
||||
private SortedSet sortedSet;
|
||||
|
||||
private Map map;
|
||||
|
||||
private SortedMap sortedMap;
|
||||
|
||||
|
||||
public IndexedTestBean() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public IndexedTestBean(boolean populate) {
|
||||
if (populate) {
|
||||
populate();
|
||||
}
|
||||
}
|
||||
|
||||
public void populate() {
|
||||
TestBean tb0 = new TestBean("name0", 0);
|
||||
TestBean tb1 = new TestBean("name1", 0);
|
||||
TestBean tb2 = new TestBean("name2", 0);
|
||||
TestBean tb3 = new TestBean("name3", 0);
|
||||
TestBean tb4 = new TestBean("name4", 0);
|
||||
TestBean tb5 = new TestBean("name5", 0);
|
||||
TestBean tb6 = new TestBean("name6", 0);
|
||||
TestBean tb7 = new TestBean("name7", 0);
|
||||
TestBean tbX = new TestBean("nameX", 0);
|
||||
TestBean tbY = new TestBean("nameY", 0);
|
||||
this.array = new TestBean[] {tb0, tb1};
|
||||
this.list = new ArrayList();
|
||||
this.list.add(tb2);
|
||||
this.list.add(tb3);
|
||||
this.set = new TreeSet();
|
||||
this.set.add(tb6);
|
||||
this.set.add(tb7);
|
||||
this.map = new HashMap();
|
||||
this.map.put("key1", tb4);
|
||||
this.map.put("key2", tb5);
|
||||
this.map.put("key.3", tb5);
|
||||
List list = new ArrayList();
|
||||
list.add(tbX);
|
||||
list.add(tbY);
|
||||
this.map.put("key4", list);
|
||||
}
|
||||
|
||||
|
||||
public TestBean[] getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(TestBean[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public Collection getCollection() {
|
||||
return collection;
|
||||
}
|
||||
|
||||
public void setCollection(Collection collection) {
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
public List getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public Set getSet() {
|
||||
return set;
|
||||
}
|
||||
|
||||
public void setSet(Set set) {
|
||||
this.set = set;
|
||||
}
|
||||
|
||||
public SortedSet getSortedSet() {
|
||||
return sortedSet;
|
||||
}
|
||||
|
||||
public void setSortedSet(SortedSet sortedSet) {
|
||||
this.sortedSet = sortedSet;
|
||||
}
|
||||
|
||||
public Map getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public void setMap(Map map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public SortedMap getSortedMap() {
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
public void setSortedMap(SortedMap sortedMap) {
|
||||
this.sortedMap = sortedMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
/**
|
||||
* Simple nested test bean used for testing bean factories, AOP framework etc.
|
||||
*
|
||||
* @author Trevor D. Cook
|
||||
* @since 30.09.2003
|
||||
*/
|
||||
public class NestedTestBean implements INestedTestBean {
|
||||
|
||||
private String company = "";
|
||||
|
||||
public NestedTestBean() {
|
||||
}
|
||||
|
||||
public NestedTestBean(String company) {
|
||||
setCompany(company);
|
||||
}
|
||||
|
||||
public void setCompany(String company) {
|
||||
this.company = (company != null ? company : "");
|
||||
}
|
||||
|
||||
public String getCompany() {
|
||||
return company;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof NestedTestBean)) {
|
||||
return false;
|
||||
}
|
||||
NestedTestBean ntb = (NestedTestBean) obj;
|
||||
return this.company.equals(ntb.company);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.company.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "NestedTestBean: " + this.company;
|
||||
}
|
||||
|
||||
}
|
||||
437
spring-tx/src/test/java/org/springframework/beans/TestBean.java
Normal file
437
spring-tx/src/test/java/org/springframework/beans/TestBean.java
Normal file
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Simple test bean used for testing bean factories, the AOP framework etc.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 15 April 2001
|
||||
*/
|
||||
public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOther, Comparable {
|
||||
|
||||
private String beanName;
|
||||
|
||||
private String country;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private boolean postProcessed;
|
||||
|
||||
private String name;
|
||||
|
||||
private String sex;
|
||||
|
||||
private int age;
|
||||
|
||||
private boolean jedi;
|
||||
|
||||
private ITestBean[] spouses;
|
||||
|
||||
private String touchy;
|
||||
|
||||
private String[] stringArray;
|
||||
|
||||
private Integer[] someIntegerArray;
|
||||
|
||||
private Date date = new Date();
|
||||
|
||||
private Float myFloat = new Float(0.0);
|
||||
|
||||
private Collection friends = new LinkedList();
|
||||
|
||||
private Set someSet = new HashSet();
|
||||
|
||||
private Map someMap = new HashMap();
|
||||
|
||||
private List someList = new ArrayList();
|
||||
|
||||
private Properties someProperties = new Properties();
|
||||
|
||||
private INestedTestBean doctor = new NestedTestBean();
|
||||
|
||||
private INestedTestBean lawyer = new NestedTestBean();
|
||||
|
||||
private IndexedTestBean nestedIndexedBean;
|
||||
|
||||
private boolean destroyed;
|
||||
|
||||
private Number someNumber;
|
||||
|
||||
private Colour favouriteColour;
|
||||
|
||||
private Boolean someBoolean;
|
||||
|
||||
private List otherColours;
|
||||
|
||||
private List pets;
|
||||
|
||||
|
||||
public TestBean() {
|
||||
}
|
||||
|
||||
public TestBean(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TestBean(ITestBean spouse) {
|
||||
this.spouses = new ITestBean[] {spouse};
|
||||
}
|
||||
|
||||
public TestBean(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public TestBean(ITestBean spouse, Properties someProperties) {
|
||||
this.spouses = new ITestBean[] {spouse};
|
||||
this.someProperties = someProperties;
|
||||
}
|
||||
|
||||
public TestBean(List someList) {
|
||||
this.someList = someList;
|
||||
}
|
||||
|
||||
public TestBean(Set someSet) {
|
||||
this.someSet = someSet;
|
||||
}
|
||||
|
||||
public TestBean(Map someMap) {
|
||||
this.someMap = someMap;
|
||||
}
|
||||
|
||||
public TestBean(Properties someProperties) {
|
||||
this.someProperties = someProperties;
|
||||
}
|
||||
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
public void setPostProcessed(boolean postProcessed) {
|
||||
this.postProcessed = postProcessed;
|
||||
}
|
||||
|
||||
public boolean isPostProcessed() {
|
||||
return postProcessed;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public void setSex(String sex) {
|
||||
this.sex = sex;
|
||||
if (this.name == null) {
|
||||
this.name = sex;
|
||||
}
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public boolean isJedi() {
|
||||
return jedi;
|
||||
}
|
||||
|
||||
public void setJedi(boolean jedi) {
|
||||
this.jedi = jedi;
|
||||
}
|
||||
|
||||
public ITestBean getSpouse() {
|
||||
return (spouses != null ? spouses[0] : null);
|
||||
}
|
||||
|
||||
public void setSpouse(ITestBean spouse) {
|
||||
this.spouses = new ITestBean[] {spouse};
|
||||
}
|
||||
|
||||
public ITestBean[] getSpouses() {
|
||||
return spouses;
|
||||
}
|
||||
|
||||
public String getTouchy() {
|
||||
return touchy;
|
||||
}
|
||||
|
||||
public void setTouchy(String touchy) throws Exception {
|
||||
if (touchy.indexOf('.') != -1) {
|
||||
throw new Exception("Can't contain a .");
|
||||
}
|
||||
if (touchy.indexOf(',') != -1) {
|
||||
throw new NumberFormatException("Number format exception: contains a ,");
|
||||
}
|
||||
this.touchy = touchy;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String[] getStringArray() {
|
||||
return stringArray;
|
||||
}
|
||||
|
||||
public void setStringArray(String[] stringArray) {
|
||||
this.stringArray = stringArray;
|
||||
}
|
||||
|
||||
public Integer[] getSomeIntegerArray() {
|
||||
return someIntegerArray;
|
||||
}
|
||||
|
||||
public void setSomeIntegerArray(Integer[] someIntegerArray) {
|
||||
this.someIntegerArray = someIntegerArray;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public Float getMyFloat() {
|
||||
return myFloat;
|
||||
}
|
||||
|
||||
public void setMyFloat(Float myFloat) {
|
||||
this.myFloat = myFloat;
|
||||
}
|
||||
|
||||
public Collection getFriends() {
|
||||
return friends;
|
||||
}
|
||||
|
||||
public void setFriends(Collection friends) {
|
||||
this.friends = friends;
|
||||
}
|
||||
|
||||
public Set getSomeSet() {
|
||||
return someSet;
|
||||
}
|
||||
|
||||
public void setSomeSet(Set someSet) {
|
||||
this.someSet = someSet;
|
||||
}
|
||||
|
||||
public Map getSomeMap() {
|
||||
return someMap;
|
||||
}
|
||||
|
||||
public void setSomeMap(Map someMap) {
|
||||
this.someMap = someMap;
|
||||
}
|
||||
|
||||
public List getSomeList() {
|
||||
return someList;
|
||||
}
|
||||
|
||||
public void setSomeList(List someList) {
|
||||
this.someList = someList;
|
||||
}
|
||||
|
||||
public Properties getSomeProperties() {
|
||||
return someProperties;
|
||||
}
|
||||
|
||||
public void setSomeProperties(Properties someProperties) {
|
||||
this.someProperties = someProperties;
|
||||
}
|
||||
|
||||
public INestedTestBean getDoctor() {
|
||||
return doctor;
|
||||
}
|
||||
|
||||
public void setDoctor(INestedTestBean doctor) {
|
||||
this.doctor = doctor;
|
||||
}
|
||||
|
||||
public INestedTestBean getLawyer() {
|
||||
return lawyer;
|
||||
}
|
||||
|
||||
public void setLawyer(INestedTestBean lawyer) {
|
||||
this.lawyer = lawyer;
|
||||
}
|
||||
|
||||
public Number getSomeNumber() {
|
||||
return someNumber;
|
||||
}
|
||||
|
||||
public void setSomeNumber(Number someNumber) {
|
||||
this.someNumber = someNumber;
|
||||
}
|
||||
|
||||
public Colour getFavouriteColour() {
|
||||
return favouriteColour;
|
||||
}
|
||||
|
||||
public void setFavouriteColour(Colour favouriteColour) {
|
||||
this.favouriteColour = favouriteColour;
|
||||
}
|
||||
|
||||
public Boolean getSomeBoolean() {
|
||||
return someBoolean;
|
||||
}
|
||||
|
||||
public void setSomeBoolean(Boolean someBoolean) {
|
||||
this.someBoolean = someBoolean;
|
||||
}
|
||||
|
||||
public IndexedTestBean getNestedIndexedBean() {
|
||||
return nestedIndexedBean;
|
||||
}
|
||||
|
||||
public void setNestedIndexedBean(IndexedTestBean nestedIndexedBean) {
|
||||
this.nestedIndexedBean = nestedIndexedBean;
|
||||
}
|
||||
|
||||
public List getOtherColours() {
|
||||
return otherColours;
|
||||
}
|
||||
|
||||
public void setOtherColours(List otherColours) {
|
||||
this.otherColours = otherColours;
|
||||
}
|
||||
|
||||
public List getPets() {
|
||||
return pets;
|
||||
}
|
||||
|
||||
public void setPets(List pets) {
|
||||
this.pets = pets;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.springframework.beans.ITestBean#exceptional(Throwable)
|
||||
*/
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
public void unreliableFileOperation() throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
/**
|
||||
* @see org.springframework.beans.ITestBean#returnsThis()
|
||||
*/
|
||||
public Object returnsThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.beans.IOther#absquatulate()
|
||||
*/
|
||||
public void absquatulate() {
|
||||
}
|
||||
|
||||
public int haveBirthday() {
|
||||
return age++;
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
this.destroyed = true;
|
||||
}
|
||||
|
||||
public boolean wasDestroyed() {
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || !(other instanceof TestBean)) {
|
||||
return false;
|
||||
}
|
||||
TestBean tb2 = (TestBean) other;
|
||||
return (ObjectUtils.nullSafeEquals(this.name, tb2.name) && this.age == tb2.age);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public int compareTo(Object other) {
|
||||
if (this.name != null && other instanceof TestBean) {
|
||||
return this.name.compareTo(((TestBean) other).getName());
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.parsing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class CollectingReaderEventListener implements ReaderEventListener {
|
||||
|
||||
private final List defaults = new LinkedList();
|
||||
|
||||
private final Map componentDefinitions = CollectionFactory.createLinkedMapIfPossible(8);
|
||||
|
||||
private final Map aliasMap = CollectionFactory.createLinkedMapIfPossible(8);
|
||||
|
||||
private final List imports = new LinkedList();
|
||||
|
||||
|
||||
public void defaultsRegistered(DefaultsDefinition defaultsDefinition) {
|
||||
this.defaults.add(defaultsDefinition);
|
||||
}
|
||||
|
||||
public List getDefaults() {
|
||||
return Collections.unmodifiableList(this.defaults);
|
||||
}
|
||||
|
||||
public void componentRegistered(ComponentDefinition componentDefinition) {
|
||||
this.componentDefinitions.put(componentDefinition.getName(), componentDefinition);
|
||||
}
|
||||
|
||||
public ComponentDefinition getComponentDefinition(String name) {
|
||||
return (ComponentDefinition) this.componentDefinitions.get(name);
|
||||
}
|
||||
|
||||
public ComponentDefinition[] getComponentDefinitions() {
|
||||
Collection collection = this.componentDefinitions.values();
|
||||
return (ComponentDefinition[]) collection.toArray(new ComponentDefinition[collection.size()]);
|
||||
}
|
||||
|
||||
public void aliasRegistered(AliasDefinition aliasDefinition) {
|
||||
List aliases = (List) this.aliasMap.get(aliasDefinition.getBeanName());
|
||||
if(aliases == null) {
|
||||
aliases = new ArrayList();
|
||||
this.aliasMap.put(aliasDefinition.getBeanName(), aliases);
|
||||
}
|
||||
aliases.add(aliasDefinition);
|
||||
}
|
||||
|
||||
public List getAliases(String beanName) {
|
||||
List aliases = (List) this.aliasMap.get(beanName);
|
||||
return aliases == null ? null : Collections.unmodifiableList(aliases);
|
||||
}
|
||||
|
||||
public void importProcessed(ImportDefinition importDefinition) {
|
||||
this.imports.add(importDefinition);
|
||||
}
|
||||
|
||||
public List getImports() {
|
||||
return Collections.unmodifiableList(this.imports);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.dao.annotation;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.support.DataAccessUtilsTests.MapPersistenceExceptionTranslator;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* Tests for PersistenceExceptionTranslationAdvisor's exception translation, as applied by
|
||||
* PersistenceExceptionTranslationPostProcessor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class PersistenceExceptionTranslationAdvisorTests extends TestCase {
|
||||
|
||||
private RuntimeException doNotTranslate = new RuntimeException();
|
||||
|
||||
private PersistenceException persistenceException1 = new PersistenceException();
|
||||
|
||||
protected RepositoryInterface createProxy(RepositoryInterfaceImpl target) {
|
||||
MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator();
|
||||
mpet.addTranslation(persistenceException1, new InvalidDataAccessApiUsageException("", persistenceException1));
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addInterface(RepositoryInterface.class);
|
||||
addPersistenceExceptionTranslation(pf, mpet);
|
||||
return (RepositoryInterface) pf.getProxy();
|
||||
}
|
||||
|
||||
protected void addPersistenceExceptionTranslation(ProxyFactory pf, PersistenceExceptionTranslator pet) {
|
||||
pf.addAdvisor(new PersistenceExceptionTranslationAdvisor(pet, Repository.class));
|
||||
}
|
||||
|
||||
public void testNoTranslationNeeded() {
|
||||
RepositoryInterfaceImpl target = new RepositoryInterfaceImpl();
|
||||
RepositoryInterface ri = createProxy(target);
|
||||
|
||||
ri.noThrowsClause();
|
||||
ri.throwsPersistenceException();
|
||||
|
||||
target.setBehavior(persistenceException1);
|
||||
try {
|
||||
ri.noThrowsClause();
|
||||
fail();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
assertSame(persistenceException1, ex);
|
||||
}
|
||||
try {
|
||||
ri.throwsPersistenceException();
|
||||
fail();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
assertSame(persistenceException1, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTranslationNotNeededForTheseExceptions() {
|
||||
RepositoryInterfaceImpl target = new StereotypedRepositoryInterfaceImpl();
|
||||
RepositoryInterface ri = createProxy(target);
|
||||
|
||||
ri.noThrowsClause();
|
||||
ri.throwsPersistenceException();
|
||||
|
||||
target.setBehavior(doNotTranslate);
|
||||
try {
|
||||
ri.noThrowsClause();
|
||||
fail();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
assertSame(doNotTranslate, ex);
|
||||
}
|
||||
try {
|
||||
ri.throwsPersistenceException();
|
||||
fail();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
assertSame(doNotTranslate, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTranslationNeededForTheseExceptions() {
|
||||
doTestTranslationNeededForTheseExceptions(new StereotypedRepositoryInterfaceImpl());
|
||||
}
|
||||
|
||||
public void testTranslationNeededForTheseExceptionsOnSuperclass() {
|
||||
doTestTranslationNeededForTheseExceptions(new MyStereotypedRepositoryInterfaceImpl());
|
||||
}
|
||||
|
||||
public void testTranslationNeededForTheseExceptionsWithCustomStereotype() {
|
||||
doTestTranslationNeededForTheseExceptions(new CustomStereotypedRepositoryInterfaceImpl());
|
||||
}
|
||||
|
||||
public void testTranslationNeededForTheseExceptionsOnInterface() {
|
||||
doTestTranslationNeededForTheseExceptions(new MyInterfaceStereotypedRepositoryInterfaceImpl());
|
||||
}
|
||||
|
||||
public void testTranslationNeededForTheseExceptionsOnInheritedInterface() {
|
||||
doTestTranslationNeededForTheseExceptions(new MyInterfaceInheritedStereotypedRepositoryInterfaceImpl());
|
||||
}
|
||||
|
||||
private void doTestTranslationNeededForTheseExceptions(RepositoryInterfaceImpl target) {
|
||||
RepositoryInterface ri = createProxy(target);
|
||||
|
||||
target.setBehavior(persistenceException1);
|
||||
try {
|
||||
ri.noThrowsClause();
|
||||
fail();
|
||||
}
|
||||
catch (DataAccessException ex) {
|
||||
// Expected
|
||||
assertSame(persistenceException1, ex.getCause());
|
||||
}
|
||||
catch (PersistenceException ex) {
|
||||
fail("Should have been translated");
|
||||
}
|
||||
|
||||
try {
|
||||
ri.throwsPersistenceException();
|
||||
fail();
|
||||
}
|
||||
catch (PersistenceException ex) {
|
||||
assertSame(persistenceException1, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface RepositoryInterface {
|
||||
|
||||
void noThrowsClause();
|
||||
|
||||
void throwsPersistenceException() throws PersistenceException;
|
||||
}
|
||||
|
||||
|
||||
public static class RepositoryInterfaceImpl implements RepositoryInterface {
|
||||
|
||||
private RuntimeException runtimeException;
|
||||
|
||||
public void setBehavior(RuntimeException rex) {
|
||||
this.runtimeException = rex;
|
||||
}
|
||||
|
||||
public void noThrowsClause() {
|
||||
if (runtimeException != null) {
|
||||
throw runtimeException;
|
||||
}
|
||||
}
|
||||
|
||||
public void throwsPersistenceException() throws PersistenceException {
|
||||
if (runtimeException != null) {
|
||||
throw runtimeException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Repository
|
||||
public static class StereotypedRepositoryInterfaceImpl extends RepositoryInterfaceImpl {
|
||||
// Extends above class just to add repository annotation
|
||||
}
|
||||
|
||||
|
||||
public static class MyStereotypedRepositoryInterfaceImpl extends StereotypedRepositoryInterfaceImpl {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@MyRepository
|
||||
public static class CustomStereotypedRepositoryInterfaceImpl extends RepositoryInterfaceImpl {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Repository
|
||||
public @interface MyRepository {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Repository
|
||||
public interface StereotypedInterface {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class MyInterfaceStereotypedRepositoryInterfaceImpl extends RepositoryInterfaceImpl
|
||||
implements StereotypedInterface {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public interface StereotypedInheritingInterface extends StereotypedInterface {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class MyInterfaceInheritedStereotypedRepositoryInterfaceImpl extends RepositoryInterfaceImpl
|
||||
implements StereotypedInheritingInterface {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.dao.annotation;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* Tests for standalone usage of a PersistenceExceptionTranslationInterceptor, as explicit advice bean in a BeanFactory
|
||||
* rather than applied as part of a PersistenceExceptionTranslationAdvisor.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class PersistenceExceptionTranslationInterceptorTests extends PersistenceExceptionTranslationAdvisorTests {
|
||||
|
||||
@Override
|
||||
protected void addPersistenceExceptionTranslation(ProxyFactory pf, PersistenceExceptionTranslator pet) {
|
||||
if (AnnotationUtils.findAnnotation(pf.getTargetClass(), Repository.class) != null) {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("peti", new RootBeanDefinition(PersistenceExceptionTranslationInterceptor.class));
|
||||
bf.registerSingleton("pet", pet);
|
||||
pf.addAdvice((PersistenceExceptionTranslationInterceptor) bf.getBean("peti"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.dao.annotation;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisorTests.RepositoryInterface;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisorTests.RepositoryInterfaceImpl;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisorTests.StereotypedRepositoryInterfaceImpl;
|
||||
import org.springframework.dao.support.ChainedPersistenceExceptionTranslator;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* Unit tests for PersistenceExceptionTranslationPostProcessor. Does not test translation; there are separate unit tests
|
||||
* for the Spring AOP Advisor. Just checks whether proxying occurs correctly, as a unit test should.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class PersistenceExceptionTranslationPostProcessorTests extends TestCase {
|
||||
|
||||
public void testFailsWithNoPersistenceExceptionTranslators() {
|
||||
GenericApplicationContext gac = new GenericApplicationContext();
|
||||
gac.registerBeanDefinition("translator",
|
||||
new RootBeanDefinition(PersistenceExceptionTranslationPostProcessor.class));
|
||||
gac.registerBeanDefinition("proxied", new RootBeanDefinition(StereotypedRepositoryInterfaceImpl.class));
|
||||
try {
|
||||
gac.refresh();
|
||||
fail("Should fail with no translators");
|
||||
}
|
||||
catch (BeansException ex) {
|
||||
// Ok
|
||||
}
|
||||
}
|
||||
|
||||
public void testProxiesCorrectly() {
|
||||
GenericApplicationContext gac = new GenericApplicationContext();
|
||||
gac.registerBeanDefinition("translator",
|
||||
new RootBeanDefinition(PersistenceExceptionTranslationPostProcessor.class));
|
||||
gac.registerBeanDefinition("notProxied", new RootBeanDefinition(RepositoryInterfaceImpl.class));
|
||||
gac.registerBeanDefinition("proxied", new RootBeanDefinition(StereotypedRepositoryInterfaceImpl.class));
|
||||
gac.registerBeanDefinition("classProxied", new RootBeanDefinition(RepositoryWithoutInterface.class));
|
||||
gac.registerBeanDefinition("classProxiedAndAdvised",
|
||||
new RootBeanDefinition(RepositoryWithoutInterfaceAndOtherwiseAdvised.class));
|
||||
gac.registerBeanDefinition("chainedTranslator",
|
||||
new RootBeanDefinition(ChainedPersistenceExceptionTranslator.class));
|
||||
gac.registerBeanDefinition("proxyCreator",
|
||||
BeanDefinitionBuilder.rootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class).
|
||||
addPropertyValue("order", 50).getBeanDefinition());
|
||||
gac.registerBeanDefinition("logger", new RootBeanDefinition(LogAllAspect.class));
|
||||
gac.refresh();
|
||||
|
||||
RepositoryInterface shouldNotBeProxied = (RepositoryInterface) gac.getBean("notProxied");
|
||||
assertFalse(AopUtils.isAopProxy(shouldNotBeProxied));
|
||||
RepositoryInterface shouldBeProxied = (RepositoryInterface) gac.getBean("proxied");
|
||||
assertTrue(AopUtils.isAopProxy(shouldBeProxied));
|
||||
RepositoryWithoutInterface rwi = (RepositoryWithoutInterface) gac.getBean("classProxied");
|
||||
assertTrue(AopUtils.isAopProxy(rwi));
|
||||
checkWillTranslateExceptions(rwi);
|
||||
|
||||
Additional rwi2 = (Additional) gac.getBean("classProxiedAndAdvised");
|
||||
assertTrue(AopUtils.isAopProxy(rwi2));
|
||||
rwi2.additionalMethod();
|
||||
checkWillTranslateExceptions(rwi2);
|
||||
}
|
||||
|
||||
protected void checkWillTranslateExceptions(Object o) {
|
||||
assertTrue(o instanceof Advised);
|
||||
Advised a = (Advised) o;
|
||||
for (Advisor advisor : a.getAdvisors()) {
|
||||
if (advisor instanceof PersistenceExceptionTranslationAdvisor) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
fail("No translation");
|
||||
}
|
||||
|
||||
@Repository
|
||||
public static class RepositoryWithoutInterface {
|
||||
|
||||
public void nameDoesntMatter() {
|
||||
}
|
||||
}
|
||||
|
||||
public interface Additional {
|
||||
|
||||
void additionalMethod();
|
||||
}
|
||||
|
||||
public static class RepositoryWithoutInterfaceAndOtherwiseAdvised extends StereotypedRepositoryInterfaceImpl
|
||||
implements Additional {
|
||||
|
||||
public void additionalMethod() {
|
||||
}
|
||||
}
|
||||
|
||||
@Aspect
|
||||
public static class LogAllAspect {
|
||||
|
||||
//@Before("execution(* *())")
|
||||
@Before("execution(void *.additionalMethod())")
|
||||
public void log(JoinPoint jp) {
|
||||
System.out.println("Before " + jp.getSignature().getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.dao.support;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.dao.support.DataAccessUtilsTests.MapPersistenceExceptionTranslator;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ChainedPersistenceExceptionTranslatorTests extends TestCase {
|
||||
|
||||
public void testEmpty() {
|
||||
ChainedPersistenceExceptionTranslator pet = new ChainedPersistenceExceptionTranslator();
|
||||
//MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator();
|
||||
RuntimeException in = new RuntimeException("in");
|
||||
assertSame(in, DataAccessUtils.translateIfNecessary(in, pet));
|
||||
}
|
||||
|
||||
public void testExceptionTranslationWithTranslation() {
|
||||
MapPersistenceExceptionTranslator mpet1 = new MapPersistenceExceptionTranslator();
|
||||
RuntimeException in1 = new RuntimeException("in");
|
||||
InvalidDataAccessApiUsageException out1 = new InvalidDataAccessApiUsageException("out");
|
||||
InvalidDataAccessApiUsageException out2 = new InvalidDataAccessApiUsageException("out");
|
||||
mpet1.addTranslation(in1, out1);
|
||||
|
||||
ChainedPersistenceExceptionTranslator chainedPet1 = new ChainedPersistenceExceptionTranslator();
|
||||
assertSame("Should not translate yet", in1, DataAccessUtils.translateIfNecessary(in1, chainedPet1));
|
||||
chainedPet1.addDelegate(mpet1);
|
||||
assertSame("Should now translate", out1, DataAccessUtils.translateIfNecessary(in1, chainedPet1));
|
||||
|
||||
// Now add a new translator and verify it wins
|
||||
MapPersistenceExceptionTranslator mpet2 = new MapPersistenceExceptionTranslator();
|
||||
mpet2.addTranslation(in1, out2);
|
||||
chainedPet1.addDelegate(mpet2);
|
||||
assertSame("Should still translate the same due to ordering",
|
||||
out1, DataAccessUtils.translateIfNecessary(in1, chainedPet1));
|
||||
|
||||
ChainedPersistenceExceptionTranslator chainedPet2 = new ChainedPersistenceExceptionTranslator();
|
||||
chainedPet2.addDelegate(mpet2);
|
||||
chainedPet2.addDelegate(mpet1);
|
||||
assertSame("Should translate differently due to ordering",
|
||||
out2, DataAccessUtils.translateIfNecessary(in1, chainedPet2));
|
||||
|
||||
RuntimeException in2 = new RuntimeException("in2");
|
||||
OptimisticLockingFailureException out3 = new OptimisticLockingFailureException("out2");
|
||||
assertNull(chainedPet2.translateExceptionIfPossible(in2));
|
||||
MapPersistenceExceptionTranslator mpet3 = new MapPersistenceExceptionTranslator();
|
||||
mpet3.addTranslation(in2, out3);
|
||||
chainedPet2.addDelegate(mpet3);
|
||||
assertSame(out3, chainedPet2.translateExceptionIfPossible(in2));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.dao.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.TypeMismatchDataAccessException;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 20.10.2004
|
||||
*/
|
||||
public class DataAccessUtilsTests extends TestCase {
|
||||
|
||||
public void testWithEmptyCollection() {
|
||||
Collection col = new HashSet();
|
||||
|
||||
assertNull(DataAccessUtils.uniqueResult(col));
|
||||
|
||||
try {
|
||||
DataAccessUtils.requiredUniqueResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(0, ex.getActualSize());
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.objectResult(col, String.class);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(0, ex.getActualSize());
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.intResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(0, ex.getActualSize());
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.longResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(0, ex.getActualSize());
|
||||
}
|
||||
}
|
||||
|
||||
public void testWithTooLargeCollection() {
|
||||
Collection col = new HashSet();
|
||||
col.add("test1");
|
||||
col.add("test2");
|
||||
|
||||
try {
|
||||
DataAccessUtils.uniqueResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(2, ex.getActualSize());
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.requiredUniqueResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(2, ex.getActualSize());
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.objectResult(col, String.class);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(2, ex.getActualSize());
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.intResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(2, ex.getActualSize());
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.longResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(2, ex.getActualSize());
|
||||
}
|
||||
}
|
||||
|
||||
public void testWithInteger() {
|
||||
Collection col = new HashSet();
|
||||
col.add(new Integer(5));
|
||||
|
||||
assertEquals(new Integer(5), DataAccessUtils.uniqueResult(col));
|
||||
assertEquals(new Integer(5), DataAccessUtils.requiredUniqueResult(col));
|
||||
assertEquals(new Integer(5), DataAccessUtils.objectResult(col, Integer.class));
|
||||
assertEquals("5", DataAccessUtils.objectResult(col, String.class));
|
||||
assertEquals(5, DataAccessUtils.intResult(col));
|
||||
assertEquals(5, DataAccessUtils.longResult(col));
|
||||
}
|
||||
|
||||
public void testWithSameIntegerInstanceTwice() {
|
||||
Integer i = new Integer(5);
|
||||
Collection col = new ArrayList();
|
||||
col.add(i);
|
||||
col.add(i);
|
||||
|
||||
assertEquals(new Integer(5), DataAccessUtils.uniqueResult(col));
|
||||
assertEquals(new Integer(5), DataAccessUtils.requiredUniqueResult(col));
|
||||
assertEquals(new Integer(5), DataAccessUtils.objectResult(col, Integer.class));
|
||||
assertEquals("5", DataAccessUtils.objectResult(col, String.class));
|
||||
assertEquals(5, DataAccessUtils.intResult(col));
|
||||
assertEquals(5, DataAccessUtils.longResult(col));
|
||||
}
|
||||
|
||||
public void testWithEquivalentIntegerInstanceTwice() {
|
||||
Collection col = new ArrayList();
|
||||
col.add(new Integer(5));
|
||||
col.add(new Integer(5));
|
||||
|
||||
try {
|
||||
DataAccessUtils.uniqueResult(col);
|
||||
fail("Should have thrown IncorrectResultSizeDataAccessException");
|
||||
}
|
||||
catch (IncorrectResultSizeDataAccessException ex) {
|
||||
// expected
|
||||
assertEquals(1, ex.getExpectedSize());
|
||||
assertEquals(2, ex.getActualSize());
|
||||
}
|
||||
}
|
||||
|
||||
public void testWithLong() {
|
||||
Collection col = new HashSet();
|
||||
col.add(new Long(5));
|
||||
|
||||
assertEquals(new Long(5), DataAccessUtils.uniqueResult(col));
|
||||
assertEquals(new Long(5), DataAccessUtils.requiredUniqueResult(col));
|
||||
assertEquals(new Long(5), DataAccessUtils.objectResult(col, Long.class));
|
||||
assertEquals("5", DataAccessUtils.objectResult(col, String.class));
|
||||
assertEquals(5, DataAccessUtils.intResult(col));
|
||||
assertEquals(5, DataAccessUtils.longResult(col));
|
||||
}
|
||||
|
||||
public void testWithString() {
|
||||
Collection col = new HashSet();
|
||||
col.add("test1");
|
||||
|
||||
assertEquals("test1", DataAccessUtils.uniqueResult(col));
|
||||
assertEquals("test1", DataAccessUtils.requiredUniqueResult(col));
|
||||
assertEquals("test1", DataAccessUtils.objectResult(col, String.class));
|
||||
|
||||
try {
|
||||
DataAccessUtils.intResult(col);
|
||||
fail("Should have thrown TypeMismatchDataAccessException");
|
||||
}
|
||||
catch (TypeMismatchDataAccessException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.longResult(col);
|
||||
fail("Should have thrown TypeMismatchDataAccessException");
|
||||
}
|
||||
catch (TypeMismatchDataAccessException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testWithDate() {
|
||||
Date date = new Date();
|
||||
Collection col = new HashSet();
|
||||
col.add(date);
|
||||
|
||||
assertEquals(date, DataAccessUtils.uniqueResult(col));
|
||||
assertEquals(date, DataAccessUtils.requiredUniqueResult(col));
|
||||
assertEquals(date, DataAccessUtils.objectResult(col, Date.class));
|
||||
assertEquals(date.toString(), DataAccessUtils.objectResult(col, String.class));
|
||||
|
||||
try {
|
||||
DataAccessUtils.intResult(col);
|
||||
fail("Should have thrown TypeMismatchDataAccessException");
|
||||
}
|
||||
catch (TypeMismatchDataAccessException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
DataAccessUtils.longResult(col);
|
||||
fail("Should have thrown TypeMismatchDataAccessException");
|
||||
}
|
||||
catch (TypeMismatchDataAccessException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testExceptionTranslationWithNoTranslation() {
|
||||
MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator();
|
||||
RuntimeException in = new RuntimeException();
|
||||
assertSame(in, DataAccessUtils.translateIfNecessary(in, mpet));
|
||||
}
|
||||
|
||||
public void testExceptionTranslationWithTranslation() {
|
||||
MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator();
|
||||
RuntimeException in = new RuntimeException("in");
|
||||
InvalidDataAccessApiUsageException out = new InvalidDataAccessApiUsageException("out");
|
||||
mpet.addTranslation(in, out);
|
||||
assertSame(out, DataAccessUtils.translateIfNecessary(in, mpet));
|
||||
}
|
||||
|
||||
|
||||
public static class MapPersistenceExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
/**
|
||||
* Map<RuntimeException,RuntimeException>: in to out
|
||||
*/
|
||||
private Map translations = new HashMap();
|
||||
|
||||
public void addTranslation(RuntimeException in, RuntimeException out) {
|
||||
this.translations.put(in, out);
|
||||
}
|
||||
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return (DataAccessException) translations.get(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jca.cci;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.Interaction;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.LocalTransaction;
|
||||
import javax.resource.cci.Record;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.jca.cci.core.CciTemplate;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* @author Thierry Templier
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class CciLocalTransactionTests {
|
||||
|
||||
/**
|
||||
* Test if a transaction ( begin / commit ) is executed on the
|
||||
* LocalTransaction when CciLocalTransactionManager is specified as
|
||||
* transaction manager.
|
||||
*/
|
||||
@Test
|
||||
public void testLocalTransactionCommit() throws ResourceException {
|
||||
final ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
LocalTransaction localTransaction = createMock(LocalTransaction.class);
|
||||
final Record record = createMock(Record.class);
|
||||
final InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.getLocalTransaction()).andReturn(localTransaction);
|
||||
|
||||
localTransaction.begin();
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, record, record)).andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
expect(connection.getLocalTransaction()).andReturn(localTransaction);
|
||||
|
||||
localTransaction.commit();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, localTransaction, interaction, record);
|
||||
|
||||
org.springframework.jca.cci.connection.CciLocalTransactionManager tm = new org.springframework.jca.cci.connection.CciLocalTransactionManager();
|
||||
tm.setConnectionFactory(connectionFactory);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(connectionFactory));
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, record, record);
|
||||
}
|
||||
});
|
||||
|
||||
verify(connectionFactory, connection, localTransaction, interaction, record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a transaction ( begin / rollback ) is executed on the
|
||||
* LocalTransaction when CciLocalTransactionManager is specified as
|
||||
* transaction manager and a non-checked exception is thrown.
|
||||
*/
|
||||
@Test
|
||||
public void testLocalTransactionRollback() throws ResourceException {
|
||||
final ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
LocalTransaction localTransaction = createMock(LocalTransaction.class);
|
||||
final Record record = createMock(Record.class);
|
||||
final InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.getLocalTransaction()).andReturn(localTransaction);
|
||||
|
||||
localTransaction.begin();
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, record, record)).andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
expect(connection.getLocalTransaction()).andReturn(localTransaction);
|
||||
|
||||
localTransaction.rollback();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, localTransaction, interaction, record);
|
||||
|
||||
org.springframework.jca.cci.connection.CciLocalTransactionManager tm = new org.springframework.jca.cci.connection.CciLocalTransactionManager();
|
||||
tm.setConnectionFactory(connectionFactory);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
try {
|
||||
tt.execute(new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(connectionFactory));
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, record, record);
|
||||
throw new DataRetrievalFailureException("error");
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
|
||||
verify(connectionFactory, connection, localTransaction, interaction, record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,709 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jca.cci;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.resource.NotSupportedException;
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.ConnectionSpec;
|
||||
import javax.resource.cci.IndexedRecord;
|
||||
import javax.resource.cci.Interaction;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.MappedRecord;
|
||||
import javax.resource.cci.Record;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
import javax.resource.cci.ResultSet;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter;
|
||||
import org.springframework.jca.cci.connection.NotSupportedRecordFactory;
|
||||
import org.springframework.jca.cci.core.CciTemplate;
|
||||
import org.springframework.jca.cci.core.ConnectionCallback;
|
||||
import org.springframework.jca.cci.core.InteractionCallback;
|
||||
import org.springframework.jca.cci.core.RecordCreator;
|
||||
import org.springframework.jca.cci.core.RecordExtractor;
|
||||
|
||||
/**
|
||||
* @author Thierry Templier
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class CciTemplateTests {
|
||||
|
||||
@Test
|
||||
public void testCreateIndexedRecord() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
IndexedRecord indexedRecord = createMock(IndexedRecord.class);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(recordFactory.createIndexedRecord("name")).andReturn(
|
||||
indexedRecord);
|
||||
|
||||
replay(connectionFactory, recordFactory);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.createIndexedRecord("name");
|
||||
|
||||
verify(connectionFactory, recordFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMappedRecord() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
MappedRecord mappedRecord = createMock(MappedRecord.class);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(recordFactory.createMappedRecord("name"))
|
||||
.andReturn(mappedRecord);
|
||||
|
||||
replay(connectionFactory, recordFactory);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.createMappedRecord("name");
|
||||
|
||||
verify(connectionFactory, recordFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputOutput() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord))
|
||||
.andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, inputRecord, outputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteWithCreatorAndRecordFactoryNotSupported()
|
||||
throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
final Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andThrow(
|
||||
new NotSupportedException("not supported"));
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord))
|
||||
.andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.setOutputRecordCreator(new RecordCreator() {
|
||||
public Record createRecord(RecordFactory recordFactory) {
|
||||
assertTrue(recordFactory instanceof NotSupportedRecordFactory);
|
||||
return outputRecord;
|
||||
}
|
||||
});
|
||||
ct.execute(interactionSpec, inputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputTrueWithCreator2()
|
||||
throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordCreator creator = createMock(RecordCreator.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
final Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(creator.createRecord(recordFactory)).andReturn(outputRecord);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord))
|
||||
.andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, creator);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.setOutputRecordCreator(creator);
|
||||
ct.execute(interactionSpec, inputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction, creator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputFalse() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord)).andReturn(
|
||||
outputRecord);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, inputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTemplateExecuteInputExtractorTrueWithCreator()
|
||||
throws ResourceException, SQLException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordExtractor<Object> extractor = createMock(RecordExtractor.class);
|
||||
RecordCreator creator = createMock(RecordCreator.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(creator.createRecord(recordFactory)).andReturn(outputRecord);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord))
|
||||
.andReturn(true);
|
||||
|
||||
expect(extractor.extractData(outputRecord)).andStubReturn(new Object());
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, extractor, creator);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.setOutputRecordCreator(creator);
|
||||
ct.execute(interactionSpec, inputRecord, extractor);
|
||||
|
||||
verify(connectionFactory, connection, interaction, extractor, creator);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTemplateExecuteInputExtractorFalse()
|
||||
throws ResourceException, SQLException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordExtractor<Object> extractor = createMock(RecordExtractor.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord)).andReturn(
|
||||
outputRecord);
|
||||
|
||||
expect(extractor.extractData(outputRecord)).andStubReturn(new Object());
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, extractor);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, inputRecord, extractor);
|
||||
|
||||
verify(connectionFactory, connection, interaction, extractor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputGeneratorTrueWithCreator()
|
||||
throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordCreator generator = createMock(RecordCreator.class);
|
||||
RecordCreator creator = createMock(RecordCreator.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(generator.createRecord(recordFactory)).andReturn(inputRecord);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(creator.createRecord(recordFactory)).andReturn(outputRecord);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord))
|
||||
.andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, generator, creator);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.setOutputRecordCreator(creator);
|
||||
ct.execute(interactionSpec, generator);
|
||||
|
||||
verify(connectionFactory, connection, interaction, generator, creator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputGeneratorFalse()
|
||||
throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordCreator generator = createMock(RecordCreator.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(generator.createRecord(recordFactory)).andReturn(inputRecord);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord)).andReturn(
|
||||
outputRecord);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, generator);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, generator);
|
||||
|
||||
verify(connectionFactory, connection, interaction, generator);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTemplateExecuteInputGeneratorExtractorTrueWithCreator()
|
||||
throws ResourceException, SQLException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordCreator generator = createMock(RecordCreator.class);
|
||||
RecordExtractor<Object> extractor = createMock(RecordExtractor.class);
|
||||
RecordCreator creator = createMock(RecordCreator.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
Object obj = new Object();
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(creator.createRecord(recordFactory)).andReturn(outputRecord);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(generator.createRecord(recordFactory)).andReturn(inputRecord);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord))
|
||||
.andReturn(true);
|
||||
|
||||
expect(extractor.extractData(outputRecord)).andStubReturn(obj);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, generator, creator,
|
||||
extractor);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.setOutputRecordCreator(creator);
|
||||
assertEquals(obj, ct.execute(interactionSpec, generator, extractor));
|
||||
|
||||
verify(connectionFactory, connection, interaction, generator, creator,
|
||||
extractor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTemplateExecuteInputGeneratorExtractorFalse()
|
||||
throws ResourceException, SQLException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordCreator generator = createMock(RecordCreator.class);
|
||||
RecordExtractor<Object> extractor = createMock(RecordExtractor.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(generator.createRecord(recordFactory)).andReturn(inputRecord);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord)).andReturn(
|
||||
outputRecord);
|
||||
|
||||
expect(extractor.extractData(outputRecord)).andStubReturn(new Object());
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, generator, extractor);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, generator, extractor);
|
||||
|
||||
verify(connectionFactory, connection, interaction, generator, extractor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputOutputConnectionSpec()
|
||||
throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
ConnectionSpec connectionSpec = createMock(ConnectionSpec.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection(connectionSpec)).andReturn(
|
||||
connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord))
|
||||
.andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
ConnectionSpecConnectionFactoryAdapter adapter = new ConnectionSpecConnectionFactoryAdapter();
|
||||
adapter.setTargetConnectionFactory(connectionFactory);
|
||||
adapter.setConnectionSpec(connectionSpec);
|
||||
CciTemplate ct = new CciTemplate(adapter);
|
||||
ct.execute(interactionSpec, inputRecord, outputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTemplateExecuteInputOutputResultsSetFalse()
|
||||
throws ResourceException, SQLException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
Record record = createMock(Record.class);
|
||||
ResultSet resultset = createMock(ResultSet.class);
|
||||
RecordCreator generator = createMock(RecordCreator.class);
|
||||
RecordExtractor<Object> extractor = createMock(RecordExtractor.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(generator.createRecord(recordFactory)).andReturn(record);
|
||||
|
||||
expect(interaction.execute(interactionSpec, record)).andReturn(
|
||||
resultset);
|
||||
|
||||
expect(extractor.extractData(resultset)).andStubReturn(new Object());
|
||||
|
||||
resultset.close();
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, generator,
|
||||
extractor, resultset);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, generator, extractor);
|
||||
|
||||
verify(connectionFactory, connection, interaction, generator,
|
||||
extractor, resultset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTemplateExecuteConnectionCallback()
|
||||
throws ResourceException, SQLException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
ConnectionCallback<Object> connectionCallback = createMock(ConnectionCallback.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connectionCallback.doInConnection(connection, connectionFactory))
|
||||
.andStubReturn(new Object());
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, connectionCallback);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(connectionCallback);
|
||||
|
||||
verify(connectionFactory, connection, connectionCallback);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTemplateExecuteInteractionCallback()
|
||||
throws ResourceException, SQLException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
InteractionCallback<Object> interactionCallback = createMock(InteractionCallback.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(
|
||||
interactionCallback.doInInteraction(interaction,
|
||||
connectionFactory)).andStubReturn(new Object());
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, interactionCallback);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionCallback);
|
||||
|
||||
verify(connectionFactory, connection, interaction, interactionCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputTrueTrueWithCreator()
|
||||
throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordCreator creator = createMock(RecordCreator.class);
|
||||
|
||||
Record inputOutputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(
|
||||
interaction.execute(interactionSpec, inputOutputRecord,
|
||||
inputOutputRecord)).andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, creator);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.setOutputRecordCreator(creator);
|
||||
ct.execute(interactionSpec, inputOutputRecord, inputOutputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction, creator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputTrueTrue() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputOutputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(
|
||||
interaction.execute(interactionSpec, inputOutputRecord,
|
||||
inputOutputRecord)).andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
ct.execute(interactionSpec, inputOutputRecord, inputOutputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateExecuteInputFalseTrue() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputOutputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputOutputRecord))
|
||||
.andReturn(null);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
CciTemplate ct = new CciTemplate(connectionFactory);
|
||||
Record tmpOutputRecord = (Record) ct.execute(interactionSpec,
|
||||
inputOutputRecord);
|
||||
assertNull(tmpOutputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jca.cci;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import javax.resource.ResourceException;
|
||||
import javax.resource.cci.Connection;
|
||||
import javax.resource.cci.ConnectionFactory;
|
||||
import javax.resource.cci.Interaction;
|
||||
import javax.resource.cci.InteractionSpec;
|
||||
import javax.resource.cci.Record;
|
||||
import javax.resource.cci.RecordFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.jca.cci.core.RecordCreator;
|
||||
import org.springframework.jca.cci.object.MappingRecordOperation;
|
||||
import org.springframework.jca.cci.object.SimpleRecordOperation;
|
||||
|
||||
/**
|
||||
* @author Thierry Templier
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class EisOperationTests {
|
||||
|
||||
@Test
|
||||
public void testSimpleRecordOperation() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
SimpleRecordOperation query = new SimpleRecordOperation(connectionFactory, interactionSpec);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord)).andReturn(outputRecord);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
query.execute(inputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRecordOperationWithExplicitOutputRecord() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
SimpleRecordOperation operation = new SimpleRecordOperation(connectionFactory, interactionSpec);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord)).andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
operation.execute(inputRecord, outputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRecordOperationWithInputOutputRecord() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
|
||||
Record inputOutputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
SimpleRecordOperation query = new SimpleRecordOperation(connectionFactory, interactionSpec);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputOutputRecord, inputOutputRecord)).andReturn(true);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction);
|
||||
|
||||
query.execute(inputOutputRecord, inputOutputRecord);
|
||||
|
||||
verify(connectionFactory, connection, interaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMappingRecordOperation() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
QueryCallDetector callDetector = createMock(QueryCallDetector.class);
|
||||
|
||||
MappingRecordOperationImpl query = new MappingRecordOperationImpl(connectionFactory, interactionSpec);
|
||||
query.setCallDetector(callDetector);
|
||||
|
||||
Object inObj = new Object();
|
||||
Object outObj = new Object();
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(callDetector.callCreateInputRecord(recordFactory, inObj)).andReturn(inputRecord);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord)).andReturn(outputRecord);
|
||||
|
||||
expect(callDetector.callExtractOutputData(outputRecord)).andReturn(outObj);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, callDetector);
|
||||
|
||||
assertSame(outObj, query.execute(inObj));
|
||||
|
||||
verify(connectionFactory, connection, interaction, callDetector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMappingRecordOperationWithOutputRecordCreator() throws ResourceException {
|
||||
ConnectionFactory connectionFactory = createMock(ConnectionFactory.class);
|
||||
Connection connection = createMock(Connection.class);
|
||||
Interaction interaction = createMock(Interaction.class);
|
||||
RecordFactory recordFactory = createMock(RecordFactory.class);
|
||||
|
||||
Record inputRecord = createMock(Record.class);
|
||||
Record outputRecord = createMock(Record.class);
|
||||
|
||||
RecordCreator outputCreator = createMock(RecordCreator.class);
|
||||
|
||||
InteractionSpec interactionSpec = createMock(InteractionSpec.class);
|
||||
|
||||
QueryCallDetector callDetector = createMock(QueryCallDetector.class);
|
||||
|
||||
MappingRecordOperationImpl query = new MappingRecordOperationImpl(connectionFactory, interactionSpec);
|
||||
query.setOutputRecordCreator(outputCreator);
|
||||
query.setCallDetector(callDetector);
|
||||
|
||||
Object inObj = new Object();
|
||||
Object outObj = new Object();
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(callDetector.callCreateInputRecord(recordFactory, inObj)).andReturn(inputRecord);
|
||||
|
||||
expect(connectionFactory.getConnection()).andReturn(connection);
|
||||
|
||||
expect(connection.createInteraction()).andReturn(interaction);
|
||||
|
||||
expect(connectionFactory.getRecordFactory()).andReturn(recordFactory);
|
||||
|
||||
expect(outputCreator.createRecord(recordFactory)).andReturn(outputRecord);
|
||||
|
||||
expect(interaction.execute(interactionSpec, inputRecord, outputRecord)).andReturn(true);
|
||||
|
||||
expect(callDetector.callExtractOutputData(outputRecord)).andReturn(outObj);
|
||||
|
||||
interaction.close();
|
||||
|
||||
connection.close();
|
||||
|
||||
replay(connectionFactory, connection, interaction, outputCreator, callDetector);
|
||||
|
||||
assertSame(outObj, query.execute(inObj));
|
||||
|
||||
verify(connectionFactory, connection, interaction, outputCreator, callDetector);
|
||||
}
|
||||
|
||||
|
||||
private class MappingRecordOperationImpl extends MappingRecordOperation {
|
||||
|
||||
private QueryCallDetector callDetector;
|
||||
|
||||
public MappingRecordOperationImpl(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
|
||||
super(connectionFactory, interactionSpec);
|
||||
}
|
||||
|
||||
public void setCallDetector(QueryCallDetector callDetector) {
|
||||
this.callDetector = callDetector;
|
||||
}
|
||||
|
||||
protected Record createInputRecord(RecordFactory recordFactory, Object inputObject) {
|
||||
return this.callDetector.callCreateInputRecord(recordFactory, inputObject);
|
||||
}
|
||||
|
||||
protected Object extractOutputData(Record outputRecord) throws ResourceException {
|
||||
return this.callDetector.callExtractOutputData(outputRecord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private interface QueryCallDetector {
|
||||
|
||||
Record callCreateInputRecord(RecordFactory recordFactory, Object inputObject);
|
||||
|
||||
Object callExtractOutputData(Record outputRecord);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jca.support;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.resource.spi.ConnectionManager;
|
||||
import javax.resource.spi.ManagedConnectionFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link LocalConnectionFactoryBean} class.
|
||||
*
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public final class LocalConnectionFactoryBeanTests {
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testManagedConnectionFactoryIsRequired() throws Exception {
|
||||
new LocalConnectionFactoryBean().afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSingleton() throws Exception {
|
||||
LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
|
||||
assertTrue(factory.isSingleton());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObjectTypeIsNullIfConnectionFactoryHasNotBeenConfigured() throws Exception {
|
||||
LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
|
||||
assertNull(factory.getObjectType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesVanillaConnectionFactoryIfNoConnectionManagerHasBeenConfigured() throws Exception {
|
||||
|
||||
final Object CONNECTION_FACTORY = new Object();
|
||||
|
||||
ManagedConnectionFactory managedConnectionFactory = createMock(ManagedConnectionFactory.class);
|
||||
|
||||
expect(managedConnectionFactory.createConnectionFactory()).andReturn(CONNECTION_FACTORY);
|
||||
replay(managedConnectionFactory);
|
||||
|
||||
LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
|
||||
factory.setManagedConnectionFactory(managedConnectionFactory);
|
||||
factory.afterPropertiesSet();
|
||||
assertEquals(CONNECTION_FACTORY, factory.getObject());
|
||||
|
||||
verify(managedConnectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatesManagedConnectionFactoryIfAConnectionManagerHasBeenConfigured() throws Exception {
|
||||
ManagedConnectionFactory managedConnectionFactory = createMock(ManagedConnectionFactory.class);
|
||||
|
||||
ConnectionManager connectionManager = createMock(ConnectionManager.class);
|
||||
|
||||
expect(managedConnectionFactory.createConnectionFactory(connectionManager)).andReturn(null);
|
||||
|
||||
replay(connectionManager, managedConnectionFactory);
|
||||
|
||||
LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
|
||||
factory.setManagedConnectionFactory(managedConnectionFactory);
|
||||
factory.setConnectionManager(connectionManager);
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
verify(connectionManager, managedConnectionFactory);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.jndi;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.jndi.JndiTemplate;
|
||||
|
||||
/**
|
||||
* Simple extension of the JndiTemplate class that always returns
|
||||
* a given object. Very useful for testing. Effectively a mock object.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ExpectedLookupTemplate extends JndiTemplate {
|
||||
|
||||
private final Map<String, Object> jndiObjects = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new JndiTemplate that will always return given objects
|
||||
* for given names. To be populated through <code>addObject</code> calls.
|
||||
* @see #addObject(String, Object)
|
||||
*/
|
||||
public ExpectedLookupTemplate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new JndiTemplate that will always return the
|
||||
* given object, but honour only requests for the given name.
|
||||
* @param name the name the client is expected to look up
|
||||
* @param object the object that will be returned
|
||||
*/
|
||||
public ExpectedLookupTemplate(String name, Object object) {
|
||||
addObject(name, object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given object to the list of JNDI objects that this
|
||||
* template will expose.
|
||||
* @param name the name the client is expected to look up
|
||||
* @param object the object that will be returned
|
||||
*/
|
||||
public void addObject(String name, Object object) {
|
||||
this.jndiObjects.put(name, object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the name is the expected name specified in the constructor,
|
||||
* return the object provided in the constructor. If the name is
|
||||
* unexpected, a respective NamingException gets thrown.
|
||||
*/
|
||||
public Object lookup(String name) throws NamingException {
|
||||
Object object = this.jndiObjects.get(name);
|
||||
if (object == null) {
|
||||
throw new NamingException("Unexpected JNDI name '" + name + "': expecting " + this.jndiObjects.keySet());
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.jndi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.naming.Binding;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NameClassPair;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NameParser;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.OperationNotSupportedException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Simple implementation of a JNDI naming context.
|
||||
* Only supports binding plain Objects to String names.
|
||||
* Mainly for test environments, but also usable for standalone applications.
|
||||
*
|
||||
* <p>This class is not intended for direct usage by applications, although it
|
||||
* can be used for example to override JndiTemplate's <code>createInitialContext</code>
|
||||
* method in unit tests. Typically, SimpleNamingContextBuilder will be used to
|
||||
* set up a JVM-level JNDI environment.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @see org.springframework.mock.jndi.SimpleNamingContextBuilder
|
||||
* @see org.springframework.jndi.JndiTemplate#createInitialContext
|
||||
*/
|
||||
public class SimpleNamingContext implements Context {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final String root;
|
||||
|
||||
private final Hashtable<String, Object> boundObjects;
|
||||
|
||||
private final Hashtable<String, Object> environment = new Hashtable<String, Object>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new naming context.
|
||||
*/
|
||||
public SimpleNamingContext() {
|
||||
this("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new naming context with the given naming root.
|
||||
*/
|
||||
public SimpleNamingContext(String root) {
|
||||
this.root = root;
|
||||
this.boundObjects = new Hashtable<String, Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new naming context with the given naming root,
|
||||
* the given name/object map, and the JNDI environment entries.
|
||||
*/
|
||||
public SimpleNamingContext(String root, Hashtable<String, Object> boundObjects, Hashtable<String, Object> env) {
|
||||
this.root = root;
|
||||
this.boundObjects = boundObjects;
|
||||
if (env != null) {
|
||||
this.environment.putAll(env);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Actual implementations of Context methods follow
|
||||
|
||||
public NamingEnumeration<NameClassPair> list(String root) throws NamingException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Listing name/class pairs under [" + root + "]");
|
||||
}
|
||||
return new NameClassPairEnumeration(this, root);
|
||||
}
|
||||
|
||||
public NamingEnumeration<Binding> listBindings(String root) throws NamingException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Listing bindings under [" + root + "]");
|
||||
}
|
||||
return new BindingEnumeration(this, root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the object with the given name.
|
||||
* <p>Note: Not intended for direct use by applications.
|
||||
* Will be used by any standard InitialContext JNDI lookups.
|
||||
* @throws javax.naming.NameNotFoundException if the object could not be found
|
||||
*/
|
||||
public Object lookup(String lookupName) throws NameNotFoundException {
|
||||
String name = this.root + lookupName;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Static JNDI lookup: [" + name + "]");
|
||||
}
|
||||
if ("".equals(name)) {
|
||||
return new SimpleNamingContext(this.root, this.boundObjects, this.environment);
|
||||
}
|
||||
Object found = this.boundObjects.get(name);
|
||||
if (found == null) {
|
||||
if (!name.endsWith("/")) {
|
||||
name = name + "/";
|
||||
}
|
||||
for (String boundName : this.boundObjects.keySet()) {
|
||||
if (boundName.startsWith(name)) {
|
||||
return new SimpleNamingContext(name, this.boundObjects, this.environment);
|
||||
}
|
||||
}
|
||||
throw new NameNotFoundException(
|
||||
"Name [" + this.root + lookupName + "] not bound; " + this.boundObjects.size() + " bindings: [" +
|
||||
StringUtils.collectionToDelimitedString(this.boundObjects.keySet(), ",") + "]");
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public Object lookupLink(String name) throws NameNotFoundException {
|
||||
return lookup(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the given object to the given name.
|
||||
* Note: Not intended for direct use by applications
|
||||
* if setting up a JVM-level JNDI environment.
|
||||
* Use SimpleNamingContextBuilder to set up JNDI bindings then.
|
||||
* @see org.springframework.mock.jndi.SimpleNamingContextBuilder#bind
|
||||
*/
|
||||
public void bind(String name, Object obj) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Static JNDI binding: [" + this.root + name + "] = [" + obj + "]");
|
||||
}
|
||||
this.boundObjects.put(this.root + name, obj);
|
||||
}
|
||||
|
||||
public void unbind(String name) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Static JNDI remove: [" + this.root + name + "]");
|
||||
}
|
||||
this.boundObjects.remove(this.root + name);
|
||||
}
|
||||
|
||||
public void rebind(String name, Object obj) {
|
||||
bind(name, obj);
|
||||
}
|
||||
|
||||
public void rename(String oldName, String newName) throws NameNotFoundException {
|
||||
Object obj = lookup(oldName);
|
||||
unbind(oldName);
|
||||
bind(newName, obj);
|
||||
}
|
||||
|
||||
public Context createSubcontext(String name) {
|
||||
String subcontextName = this.root + name;
|
||||
if (!subcontextName.endsWith("/")) {
|
||||
subcontextName += "/";
|
||||
}
|
||||
Context subcontext = new SimpleNamingContext(subcontextName, this.boundObjects, this.environment);
|
||||
bind(name, subcontext);
|
||||
return subcontext;
|
||||
}
|
||||
|
||||
public void destroySubcontext(String name) {
|
||||
unbind(name);
|
||||
}
|
||||
|
||||
public String composeName(String name, String prefix) {
|
||||
return prefix + name;
|
||||
}
|
||||
|
||||
public Hashtable<String, Object> getEnvironment() {
|
||||
return this.environment;
|
||||
}
|
||||
|
||||
public Object addToEnvironment(String propName, Object propVal) {
|
||||
return this.environment.put(propName, propVal);
|
||||
}
|
||||
|
||||
public Object removeFromEnvironment(String propName) {
|
||||
return this.environment.remove(propName);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
|
||||
// Unsupported methods follow: no support for javax.naming.Name
|
||||
|
||||
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public Object lookup(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public Object lookupLink(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public void bind(Name name, Object obj) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public void unbind(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public void rebind(Name name, Object obj) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public void rename(Name oldName, Name newName) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public Context createSubcontext(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public void destroySubcontext(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public String getNameInNamespace() throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public NameParser getNameParser(Name name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public NameParser getNameParser(String name) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
public Name composeName(Name name, Name prefix) throws NamingException {
|
||||
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]");
|
||||
}
|
||||
|
||||
|
||||
private static abstract class AbstractNamingEnumeration<T> implements NamingEnumeration<T> {
|
||||
|
||||
private Iterator<T> iterator;
|
||||
|
||||
private AbstractNamingEnumeration(SimpleNamingContext context, String proot) throws NamingException {
|
||||
if (!"".equals(proot) && !proot.endsWith("/")) {
|
||||
proot = proot + "/";
|
||||
}
|
||||
String root = context.root + proot;
|
||||
Map<String, T> contents = new HashMap<String, T>();
|
||||
for (String boundName : context.boundObjects.keySet()) {
|
||||
if (boundName.startsWith(root)) {
|
||||
int startIndex = root.length();
|
||||
int endIndex = boundName.indexOf('/', startIndex);
|
||||
String strippedName =
|
||||
(endIndex != -1 ? boundName.substring(startIndex, endIndex) : boundName.substring(startIndex));
|
||||
if (!contents.containsKey(strippedName)) {
|
||||
try {
|
||||
contents.put(strippedName, createObject(strippedName, context.lookup(proot + strippedName)));
|
||||
}
|
||||
catch (NameNotFoundException ex) {
|
||||
// cannot happen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (contents.size() == 0) {
|
||||
throw new NamingException("Invalid root: [" + context.root + proot + "]");
|
||||
}
|
||||
this.iterator = contents.values().iterator();
|
||||
}
|
||||
|
||||
protected abstract T createObject(String strippedName, Object obj);
|
||||
|
||||
public boolean hasMore() {
|
||||
return this.iterator.hasNext();
|
||||
}
|
||||
|
||||
public T next() {
|
||||
return this.iterator.next();
|
||||
}
|
||||
|
||||
public boolean hasMoreElements() {
|
||||
return this.iterator.hasNext();
|
||||
}
|
||||
|
||||
public T nextElement() {
|
||||
return this.iterator.next();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class NameClassPairEnumeration extends AbstractNamingEnumeration<NameClassPair> {
|
||||
|
||||
private NameClassPairEnumeration(SimpleNamingContext context, String root) throws NamingException {
|
||||
super(context, root);
|
||||
}
|
||||
|
||||
protected NameClassPair createObject(String strippedName, Object obj) {
|
||||
return new NameClassPair(strippedName, obj.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class BindingEnumeration extends AbstractNamingEnumeration<Binding> {
|
||||
|
||||
private BindingEnumeration(SimpleNamingContext context, String root) throws NamingException {
|
||||
super(context, root);
|
||||
}
|
||||
|
||||
protected Binding createObject(String strippedName, Object obj) {
|
||||
return new Binding(strippedName, obj);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.jndi;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.spi.InitialContextFactory;
|
||||
import javax.naming.spi.InitialContextFactoryBuilder;
|
||||
import javax.naming.spi.NamingManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Simple implementation of a JNDI naming context builder.
|
||||
*
|
||||
* <p>Mainly targeted at test environments, where each test case can
|
||||
* configure JNDI appropriately, so that <code>new InitialContext()</code>
|
||||
* will expose the required objects. Also usable for standalone applications,
|
||||
* e.g. for binding a JDBC DataSource to a well-known JNDI location, to be
|
||||
* able to use traditional J2EE data access code outside of a J2EE container.
|
||||
*
|
||||
* <p>There are various choices for DataSource implementations:
|
||||
* <ul>
|
||||
* <li>SingleConnectionDataSource (using the same Connection for all getConnection calls);
|
||||
* <li>DriverManagerDataSource (creating a new Connection on each getConnection call);
|
||||
* <li>Apache's Jakarta Commons DBCP offers BasicDataSource (a real pool).
|
||||
* </ul>
|
||||
*
|
||||
* <p>Typical usage in bootstrap code:
|
||||
*
|
||||
* <pre class="code">
|
||||
* SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
|
||||
* DataSource ds = new DriverManagerDataSource(...);
|
||||
* builder.bind("java:comp/env/jdbc/myds", ds);
|
||||
* builder.activate();</pre>
|
||||
*
|
||||
* Note that it's impossible to activate multiple builders within the same JVM,
|
||||
* due to JNDI restrictions. Thus to configure a fresh builder repeatedly, use
|
||||
* the following code to get a reference to either an already activated builder
|
||||
* or a newly activated one:
|
||||
*
|
||||
* <pre class="code">
|
||||
* SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
|
||||
* DataSource ds = new DriverManagerDataSource(...);
|
||||
* builder.bind("java:comp/env/jdbc/myds", ds);</pre>
|
||||
*
|
||||
* Note that you <i>should not</i> call <code>activate()</code> on a builder from
|
||||
* this factory method, as there will already be an activated one in any case.
|
||||
*
|
||||
* <p>An instance of this class is only necessary at setup time.
|
||||
* An application does not need to keep a reference to it after activation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @see #emptyActivatedContextBuilder()
|
||||
* @see #bind(String, Object)
|
||||
* @see #activate()
|
||||
* @see org.springframework.mock.jndi.SimpleNamingContext
|
||||
* @see org.springframework.jdbc.datasource.SingleConnectionDataSource
|
||||
* @see org.springframework.jdbc.datasource.DriverManagerDataSource
|
||||
* @see org.apache.commons.dbcp.BasicDataSource
|
||||
*/
|
||||
public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder {
|
||||
|
||||
/** An instance of this class bound to JNDI */
|
||||
private static volatile SimpleNamingContextBuilder activated;
|
||||
|
||||
private static boolean initialized = false;
|
||||
|
||||
private static final Object initializationLock = new Object();
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a SimpleNamingContextBuilder is active.
|
||||
* @return the current SimpleNamingContextBuilder instance,
|
||||
* or <code>null</code> if none
|
||||
*/
|
||||
public static SimpleNamingContextBuilder getCurrentContextBuilder() {
|
||||
return activated;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no SimpleNamingContextBuilder is already configuring JNDI,
|
||||
* create and activate one. Otherwise take the existing activate
|
||||
* SimpleNamingContextBuilder, clear it and return it.
|
||||
* <p>This is mainly intended for test suites that want to
|
||||
* reinitialize JNDI bindings from scratch repeatedly.
|
||||
* @return an empty SimpleNamingContextBuilder that can be used
|
||||
* to control JNDI bindings
|
||||
*/
|
||||
public static SimpleNamingContextBuilder emptyActivatedContextBuilder() throws NamingException {
|
||||
if (activated != null) {
|
||||
// Clear already activated context builder.
|
||||
activated.clear();
|
||||
}
|
||||
else {
|
||||
// Create and activate new context builder.
|
||||
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
|
||||
// The activate() call will cause an assignment to the activated variable.
|
||||
builder.activate();
|
||||
}
|
||||
return activated;
|
||||
}
|
||||
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Hashtable<String,Object> boundObjects = new Hashtable<String,Object>();
|
||||
|
||||
|
||||
/**
|
||||
* Register the context builder by registering it with the JNDI NamingManager.
|
||||
* Note that once this has been done, <code>new InitialContext()</code> will always
|
||||
* return a context from this factory. Use the <code>emptyActivatedContextBuilder()</code>
|
||||
* static method to get an empty context (for example, in test methods).
|
||||
* @throws IllegalStateException if there's already a naming context builder
|
||||
* registered with the JNDI NamingManager
|
||||
*/
|
||||
public void activate() throws IllegalStateException, NamingException {
|
||||
logger.info("Activating simple JNDI environment");
|
||||
synchronized (initializationLock) {
|
||||
if (!initialized) {
|
||||
if (NamingManager.hasInitialContextFactoryBuilder()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot activate SimpleNamingContextBuilder: there is already a JNDI provider registered. " +
|
||||
"Note that JNDI is a JVM-wide service, shared at the JVM system class loader level, " +
|
||||
"with no reset option. As a consequence, a JNDI provider must only be registered once per JVM.");
|
||||
}
|
||||
NamingManager.setInitialContextFactoryBuilder(this);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
activated = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily deactivate this context builder. It will remain registered with
|
||||
* the JNDI NamingManager but will delegate to the standard JNDI InitialContextFactory
|
||||
* (if configured) instead of exposing its own bound objects.
|
||||
* <p>Call <code>activate()</code> again in order to expose this context builder's own
|
||||
* bound objects again. Such activate/deactivate sequences can be applied any number
|
||||
* of times (e.g. within a larger integration test suite running in the same VM).
|
||||
* @see #activate()
|
||||
*/
|
||||
public void deactivate() {
|
||||
logger.info("Deactivating simple JNDI environment");
|
||||
activated = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all bindings in this context builder, while keeping it active.
|
||||
*/
|
||||
public void clear() {
|
||||
this.boundObjects.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the given object under the given name, for all naming contexts
|
||||
* that this context builder will generate.
|
||||
* @param name the JNDI name of the object (e.g. "java:comp/env/jdbc/myds")
|
||||
* @param obj the object to bind (e.g. a DataSource implementation)
|
||||
*/
|
||||
public void bind(String name, Object obj) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Static JNDI binding: [" + name + "] = [" + obj + "]");
|
||||
}
|
||||
this.boundObjects.put(name, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple InitialContextFactoryBuilder implementation,
|
||||
* creating a new SimpleNamingContext instance.
|
||||
* @see SimpleNamingContext
|
||||
*/
|
||||
public InitialContextFactory createInitialContextFactory(Hashtable<?,?> environment) {
|
||||
if (activated == null && environment != null) {
|
||||
Object icf = environment.get(Context.INITIAL_CONTEXT_FACTORY);
|
||||
if (icf != null) {
|
||||
Class<?> icfClass = null;
|
||||
if (icf instanceof Class) {
|
||||
icfClass = (Class<?>) icf;
|
||||
}
|
||||
else if (icf instanceof String) {
|
||||
icfClass = ClassUtils.resolveClassName((String) icf, getClass().getClassLoader());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid value type for environment key [" +
|
||||
Context.INITIAL_CONTEXT_FACTORY + "]: " + icf.getClass().getName());
|
||||
}
|
||||
if (!InitialContextFactory.class.isAssignableFrom(icfClass)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Specified class does not implement [" + InitialContextFactory.class.getName() + "]: " + icf);
|
||||
}
|
||||
try {
|
||||
return (InitialContextFactory) icfClass.newInstance();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
IllegalStateException ise =
|
||||
new IllegalStateException("Cannot instantiate specified InitialContextFactory: " + icf);
|
||||
ise.initCause(ex);
|
||||
throw ise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default case...
|
||||
return new InitialContextFactory() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Context getInitialContext(Hashtable<?,?> environment) {
|
||||
return new SimpleNamingContext("", boundObjects, (Hashtable<String, Object>) environment);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class CallCountingTransactionManager extends AbstractPlatformTransactionManager {
|
||||
|
||||
public TransactionDefinition lastDefinition;
|
||||
public int begun;
|
||||
public int commits;
|
||||
public int rollbacks;
|
||||
public int inflight;
|
||||
|
||||
protected Object doGetTransaction() {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
this.lastDefinition = definition;
|
||||
++begun;
|
||||
++inflight;
|
||||
}
|
||||
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
++commits;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
++rollbacks;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
begun = commits = rollbacks = inflight = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.mock.jndi.ExpectedLookupTemplate;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.transaction.jta.UserTransactionAdapter;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 05.08.2005
|
||||
*/
|
||||
public class JndiJtaTransactionManagerTests extends TestCase {
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookups1() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:comp/TransactionManager", true, true);
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookups2() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:/TransactionManager", true, true);
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookupsAndNoTmFound() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:/tm", false, true);
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookupsAndNoUtFound() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:/TransactionManager", true, false);
|
||||
}
|
||||
|
||||
private void doTestJtaTransactionManagerWithDefaultJndiLookups(String tmName, boolean tmFound, boolean defaultUt)
|
||||
throws Exception {
|
||||
|
||||
MockControl utControl = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut = (UserTransaction) utControl.getMock();
|
||||
if (defaultUt) {
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
ut.begin();
|
||||
utControl.setVoidCallable(1);
|
||||
ut.commit();
|
||||
utControl.setVoidCallable(1);
|
||||
}
|
||||
utControl.replay();
|
||||
|
||||
MockControl tmControl = MockControl.createControl(TransactionManager.class);
|
||||
TransactionManager tm = (TransactionManager) tmControl.getMock();
|
||||
if (!defaultUt) {
|
||||
tm.getStatus();
|
||||
tmControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
tm.getStatus();
|
||||
tmControl.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
tm.begin();
|
||||
tmControl.setVoidCallable(1);
|
||||
tm.commit();
|
||||
tmControl.setVoidCallable(1);
|
||||
}
|
||||
tmControl.replay();
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager();
|
||||
ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
|
||||
if (defaultUt) {
|
||||
jndiTemplate.addObject("java:comp/UserTransaction", ut);
|
||||
}
|
||||
jndiTemplate.addObject(tmName, tm);
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
if (tmFound) {
|
||||
assertEquals(tm, ptm.getTransactionManager());
|
||||
}
|
||||
else {
|
||||
assertNull(ptm.getTransactionManager());
|
||||
}
|
||||
|
||||
if (defaultUt) {
|
||||
assertEquals(ut, ptm.getUserTransaction());
|
||||
}
|
||||
else {
|
||||
assertTrue(ptm.getUserTransaction() instanceof UserTransactionAdapter);
|
||||
UserTransactionAdapter uta = (UserTransactionAdapter) ptm.getUserTransaction();
|
||||
assertEquals(tm, uta.getTransactionManager());
|
||||
}
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
utControl.verify();
|
||||
tmControl.verify();
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithCustomJndiLookups() throws Exception {
|
||||
MockControl utControl = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut = (UserTransaction) utControl.getMock();
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
ut.begin();
|
||||
utControl.setVoidCallable(1);
|
||||
ut.commit();
|
||||
utControl.setVoidCallable(1);
|
||||
utControl.replay();
|
||||
|
||||
MockControl tmControl = MockControl.createControl(TransactionManager.class);
|
||||
TransactionManager tm = (TransactionManager) tmControl.getMock();
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager();
|
||||
ptm.setUserTransactionName("jndi-ut");
|
||||
ptm.setTransactionManagerName("jndi-tm");
|
||||
ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
|
||||
jndiTemplate.addObject("jndi-ut", ut);
|
||||
jndiTemplate.addObject("jndi-tm", tm);
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
assertEquals(ut, ptm.getUserTransaction());
|
||||
assertEquals(tm, ptm.getTransactionManager());
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
utControl.verify();
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithNotCacheUserTransaction() throws Exception {
|
||||
MockControl utControl = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut = (UserTransaction) utControl.getMock();
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
ut.begin();
|
||||
utControl.setVoidCallable(1);
|
||||
ut.commit();
|
||||
utControl.setVoidCallable(1);
|
||||
utControl.replay();
|
||||
|
||||
MockControl ut2Control = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut2 = (UserTransaction) ut2Control.getMock();
|
||||
ut2.getStatus();
|
||||
ut2Control.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
ut2.getStatus();
|
||||
ut2Control.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
ut2.begin();
|
||||
ut2Control.setVoidCallable(1);
|
||||
ut2.commit();
|
||||
ut2Control.setVoidCallable(1);
|
||||
ut2Control.replay();
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager();
|
||||
ptm.setJndiTemplate(new ExpectedLookupTemplate("java:comp/UserTransaction", ut));
|
||||
ptm.setCacheUserTransaction(false);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
assertEquals(ut, ptm.getUserTransaction());
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
assertEquals(JtaTransactionManager.SYNCHRONIZATION_ALWAYS, ptm.getTransactionSynchronization());
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
|
||||
ptm.setJndiTemplate(new ExpectedLookupTemplate("java:comp/UserTransaction", ut2));
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
utControl.verify();
|
||||
ut2Control.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent any side-effects due to this test modifying ThreadLocals that might
|
||||
* affect subsequent tests when all tests are run in the same JVM, as with Eclipse.
|
||||
*/
|
||||
protected void tearDown() {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.SimpleTransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class MockCallbackPreferringTransactionManager implements CallbackPreferringPlatformTransactionManager {
|
||||
|
||||
private TransactionDefinition definition;
|
||||
|
||||
private TransactionStatus status;
|
||||
|
||||
|
||||
public Object execute(TransactionDefinition definition, TransactionCallback callback) throws TransactionException {
|
||||
this.definition = definition;
|
||||
this.status = new SimpleTransactionStatus();
|
||||
return callback.doInTransaction(this.status);
|
||||
}
|
||||
|
||||
public TransactionDefinition getDefinition() {
|
||||
return this.definition;
|
||||
}
|
||||
|
||||
public TransactionStatus getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void commit(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void rollback(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.xa.XAResource;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 31.08.2004
|
||||
*/
|
||||
public class MockJtaTransaction implements javax.transaction.Transaction {
|
||||
|
||||
private Synchronization synchronization;
|
||||
|
||||
public int getStatus() {
|
||||
return Status.STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
public void registerSynchronization(Synchronization synchronization) {
|
||||
this.synchronization = synchronization;
|
||||
}
|
||||
|
||||
public Synchronization getSynchronization() {
|
||||
return synchronization;
|
||||
}
|
||||
|
||||
public boolean enlistResource(XAResource xaResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean delistResource(XAResource xaResource, int i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
}
|
||||
|
||||
public void rollback() {
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 29.04.2003
|
||||
*/
|
||||
class TestTransactionManager extends AbstractPlatformTransactionManager {
|
||||
|
||||
private static final Object TRANSACTION = "transaction";
|
||||
|
||||
private final boolean existingTransaction;
|
||||
|
||||
private final boolean canCreateTransaction;
|
||||
|
||||
protected boolean begin = false;
|
||||
|
||||
protected boolean commit = false;
|
||||
|
||||
protected boolean rollback = false;
|
||||
|
||||
protected boolean rollbackOnly = false;
|
||||
|
||||
protected TestTransactionManager(boolean existingTransaction, boolean canCreateTransaction) {
|
||||
this.existingTransaction = existingTransaction;
|
||||
this.canCreateTransaction = canCreateTransaction;
|
||||
setTransactionSynchronization(SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
protected Object doGetTransaction() {
|
||||
return TRANSACTION;
|
||||
}
|
||||
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
return existingTransaction;
|
||||
}
|
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
if (!TRANSACTION.equals(transaction)) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
if (!this.canCreateTransaction) {
|
||||
throw new CannotCreateTransactionException("Cannot create transaction");
|
||||
}
|
||||
this.begin = true;
|
||||
}
|
||||
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
if (!TRANSACTION.equals(status.getTransaction())) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
this.commit = true;
|
||||
}
|
||||
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
if (!TRANSACTION.equals(status.getTransaction())) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
this.rollback = true;
|
||||
}
|
||||
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
if (!TRANSACTION.equals(status.getTransaction())) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
this.rollbackOnly = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 29.04.2003
|
||||
*/
|
||||
public class TransactionSupportTests extends TestCase {
|
||||
|
||||
public void testNoExistingTransaction() {
|
||||
PlatformTransactionManager tm = new TestTransactionManager(false, true);
|
||||
DefaultTransactionStatus status1 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
assertTrue("Must not have transaction", status1.getTransaction() == null);
|
||||
|
||||
DefaultTransactionStatus status2 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
|
||||
assertTrue("Must have transaction", status2.getTransaction() != null);
|
||||
assertTrue("Must be new transaction", status2.isNewTransaction());
|
||||
|
||||
try {
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY));
|
||||
fail("Should not have thrown NoTransactionException");
|
||||
}
|
||||
catch (IllegalTransactionStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testExistingTransaction() {
|
||||
PlatformTransactionManager tm = new TestTransactionManager(true, true);
|
||||
DefaultTransactionStatus status1 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
assertTrue("Must have transaction", status1.getTransaction() != null);
|
||||
assertTrue("Must not be new transaction", !status1.isNewTransaction());
|
||||
|
||||
DefaultTransactionStatus status2 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
|
||||
assertTrue("Must have transaction", status2.getTransaction() != null);
|
||||
assertTrue("Must not be new transaction", !status2.isNewTransaction());
|
||||
|
||||
try {
|
||||
DefaultTransactionStatus status3 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY));
|
||||
assertTrue("Must have transaction", status3.getTransaction() != null);
|
||||
assertTrue("Must not be new transaction", !status3.isNewTransaction());
|
||||
}
|
||||
catch (NoTransactionException ex) {
|
||||
fail("Should not have thrown NoTransactionException");
|
||||
}
|
||||
}
|
||||
|
||||
public void testCommitWithoutExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.commit(status);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("triggered commit", tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackWithoutExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.rollback(status);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackOnlyWithoutExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
status.setRollbackOnly();
|
||||
tm.commit(status);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testCommitWithExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(true, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.commit(status);
|
||||
assertTrue("no begin", !tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackWithExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(true, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.rollback(status);
|
||||
assertTrue("no begin", !tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("triggered rollbackOnly", tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackOnlyWithExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(true, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
status.setRollbackOnly();
|
||||
tm.commit(status);
|
||||
assertTrue("no begin", !tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("triggered rollbackOnly", tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testTransactionTemplate() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
}
|
||||
});
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("triggered commit", tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithCallbackPreference() {
|
||||
MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
|
||||
TransactionTemplate template = new TransactionTemplate(ptm);
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
}
|
||||
});
|
||||
assertSame(template, ptm.getDefinition());
|
||||
assertFalse(ptm.getStatus().isRollbackOnly());
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithException() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
final RuntimeException ex = new RuntimeException("Some application exception");
|
||||
try {
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
throw ex;
|
||||
}
|
||||
});
|
||||
fail("Should have propagated RuntimeException");
|
||||
}
|
||||
catch (RuntimeException caught) {
|
||||
// expected
|
||||
assertTrue("Correct exception", caught == ex);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithRollbackException() {
|
||||
final TransactionSystemException tex = new TransactionSystemException("system exception");
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true) {
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
super.doRollback(status);
|
||||
throw tex;
|
||||
}
|
||||
};
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
final RuntimeException ex = new RuntimeException("Some application exception");
|
||||
try {
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
throw ex;
|
||||
}
|
||||
});
|
||||
fail("Should have propagated RuntimeException");
|
||||
}
|
||||
catch (RuntimeException caught) {
|
||||
// expected
|
||||
assertTrue("Correct exception", caught == tex);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithError() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
try {
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
throw new Error("Some application error");
|
||||
}
|
||||
});
|
||||
fail("Should have propagated Error");
|
||||
}
|
||||
catch (Error err) {
|
||||
// expected
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTransactionTemplateInitialization() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate();
|
||||
template.setTransactionManager(tm);
|
||||
assertTrue("correct transaction manager set", template.getTransactionManager() == tm);
|
||||
|
||||
try {
|
||||
template.setPropagationBehaviorName("TIMEOUT_DEFAULT");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setPropagationBehaviorName("PROPAGATION_SUPPORTS");
|
||||
assertTrue("Correct propagation behavior set", template.getPropagationBehavior() == TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
|
||||
try {
|
||||
template.setPropagationBehavior(999);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
assertTrue("Correct propagation behavior set", template.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
|
||||
try {
|
||||
template.setIsolationLevelName("TIMEOUT_DEFAULT");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setIsolationLevelName("ISOLATION_SERIALIZABLE");
|
||||
assertTrue("Correct isolation level set", template.getIsolationLevel() == TransactionDefinition.ISOLATION_SERIALIZABLE);
|
||||
|
||||
try {
|
||||
template.setIsolationLevel(999);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertTrue("Correct isolation level set", template.getIsolationLevel() == TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
}
|
||||
|
||||
protected void tearDown() {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CollectingReaderEventListener;
|
||||
import org.springframework.beans.factory.parsing.ComponentDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
/**
|
||||
* @author Torsten Juergeleit
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class TxNamespaceHandlerEventTests extends TestCase {
|
||||
|
||||
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
|
||||
|
||||
|
||||
public void setUp() throws Exception {
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
|
||||
reader.setEventListener(this.eventListener);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("txNamespaceHandlerTests.xml", getClass()));
|
||||
}
|
||||
|
||||
public void testComponentEventReceived() {
|
||||
ComponentDefinition component = this.eventListener.getComponentDefinition("txAdvice");
|
||||
assertTrue(component instanceof BeanComponentDefinition);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
public class TxNamespaceHandlerTests extends TestCase {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
private Method getAgeMethod;
|
||||
|
||||
private Method setAgeMethod;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.context = new ClassPathXmlApplicationContext("txNamespaceHandlerTests.xml", getClass());
|
||||
this.getAgeMethod = ITestBean.class.getMethod("getAge", new Class[0]);
|
||||
this.setAgeMethod = ITestBean.class.getMethod("setAge", new Class[] {int.class});
|
||||
}
|
||||
|
||||
public void testIsProxy() throws Exception {
|
||||
ITestBean bean = getTestBean();
|
||||
assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
|
||||
}
|
||||
|
||||
public void testInvokeTransactional() throws Exception {
|
||||
ITestBean testBean = getTestBean();
|
||||
CallCountingTransactionManager ptm = (CallCountingTransactionManager) context.getBean("transactionManager");
|
||||
|
||||
// try with transactional
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
testBean.getName();
|
||||
assertTrue(ptm.lastDefinition.isReadOnly());
|
||||
assertEquals("Should have 1 started transaction", 1, ptm.begun);
|
||||
assertEquals("Should have 1 committed transaction", 1, ptm.commits);
|
||||
|
||||
// try with non-transaction
|
||||
testBean.haveBirthday();
|
||||
assertEquals("Should not have started another transaction", 1, ptm.begun);
|
||||
|
||||
// try with exceptional
|
||||
try {
|
||||
testBean.exceptional(new IllegalArgumentException("foo"));
|
||||
fail("Should NEVER get here");
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
assertEquals("Should have another started transaction", 2, ptm.begun);
|
||||
assertEquals("Should have 1 rolled back transaction", 1, ptm.rollbacks);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRollbackRules() {
|
||||
TransactionInterceptor txInterceptor = (TransactionInterceptor) context.getBean("txRollbackAdvice");
|
||||
TransactionAttributeSource txAttrSource = txInterceptor.getTransactionAttributeSource();
|
||||
TransactionAttribute txAttr = txAttrSource.getTransactionAttribute(getAgeMethod,ITestBean.class);
|
||||
assertTrue("should be configured to rollback on Exception",txAttr.rollbackOn(new Exception()));
|
||||
|
||||
txAttr = txAttrSource.getTransactionAttribute(setAgeMethod, ITestBean.class);
|
||||
assertFalse("should not rollback on RuntimeException",txAttr.rollbackOn(new RuntimeException()));
|
||||
}
|
||||
|
||||
private ITestBean getTestBean() {
|
||||
return (ITestBean)context.getBean("testBean");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.interceptor.NoRollbackRuleAttribute;
|
||||
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
|
||||
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationTransactionAttributeSourceTests {
|
||||
|
||||
@Test
|
||||
public void testSerializable() throws Exception {
|
||||
TestBean1 tb = new TestBean1();
|
||||
CallCountingTransactionManager ptm = new CallCountingTransactionManager();
|
||||
AnnotationTransactionAttributeSource tas = new AnnotationTransactionAttributeSource();
|
||||
TransactionInterceptor ti = new TransactionInterceptor(ptm, tas);
|
||||
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
|
||||
proxyFactory.addAdvice(ti);
|
||||
proxyFactory.setTarget(tb);
|
||||
ITestBean proxy = (ITestBean) proxyFactory.getProxy();
|
||||
proxy.getAge();
|
||||
assertEquals(1, ptm.commits);
|
||||
|
||||
ITestBean serializedProxy = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy);
|
||||
serializedProxy.getAge();
|
||||
Advised advised = (Advised) serializedProxy;
|
||||
TransactionInterceptor serializedTi = (TransactionInterceptor) advised.getAdvisors()[0].getAdvice();
|
||||
CallCountingTransactionManager serializedPtm =
|
||||
(CallCountingTransactionManager) serializedTi.getTransactionManager();
|
||||
assertEquals(2, serializedPtm.commits);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullOrEmpty() throws Exception {
|
||||
Method method = Empty.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
assertNull(atas.getTransactionAttribute(method, null));
|
||||
|
||||
// Try again in case of caching
|
||||
assertNull(atas.getTransactionAttribute(method, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the important case where the invocation is on a proxied interface method
|
||||
* but the attribute is defined on the target class.
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionAttributeDeclaredOnClassMethod() throws Exception {
|
||||
Method classMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(classMethod, TestBean1.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the important case where the invocation is on a proxied interface method
|
||||
* but the attribute is defined on the target class.
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionAttributeDeclaredOnCglibClassMethod() throws Exception {
|
||||
Method classMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
TestBean1 tb = new TestBean1();
|
||||
ProxyFactory pf = new ProxyFactory(tb);
|
||||
pf.setProxyTargetClass(true);
|
||||
Object proxy = pf.getProxy();
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(classMethod, proxy.getClass());
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case where attribute is on the interface method.
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionAttributeDeclaredOnInterfaceMethodOnly() throws Exception {
|
||||
Method interfaceMethod = ITestBean2.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(interfaceMethod, TestBean2.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when an attribute exists on both class and interface, class takes precedence.
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionAttributeOnTargetClassMethodOverridesAttributeOnInterfaceMethod() throws Exception {
|
||||
Method interfaceMethod = ITestBean3.class.getMethod("getAge", (Class[]) null);
|
||||
Method interfaceMethod2 = ITestBean3.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(interfaceMethod, TestBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRES_NEW, actual.getPropagationBehavior());
|
||||
assertEquals(TransactionAttribute.ISOLATION_REPEATABLE_READ, actual.getIsolationLevel());
|
||||
assertEquals(5, actual.getTimeout());
|
||||
assertTrue(actual.isReadOnly());
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
|
||||
TransactionAttribute actual2 = atas.getTransactionAttribute(interfaceMethod2, TestBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, actual2.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackRulesAreApplied() throws Exception {
|
||||
Method method = TestBean3.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(method, TestBean3.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute("java.lang.Exception"));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
assertTrue(actual.rollbackOn(new Exception()));
|
||||
assertFalse(actual.rollbackOn(new IOException()));
|
||||
|
||||
actual = atas.getTransactionAttribute(method, method.getDeclaringClass());
|
||||
|
||||
rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute("java.lang.Exception"));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
assertTrue(actual.rollbackOn(new Exception()));
|
||||
assertFalse(actual.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that transaction attribute is inherited from class
|
||||
* if not specified on method.
|
||||
*/
|
||||
@Test
|
||||
public void testDefaultsToClassTransactionAttribute() throws Exception {
|
||||
Method method = TestBean4.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(method, TestBean4.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomClassAttributeDetected() throws Exception {
|
||||
Method method = TestBean5.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(method, TestBean5.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomMethodAttributeDetected() throws Exception {
|
||||
Method method = TestBean6.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(method, TestBean5.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionAttributeDeclaredOnClassMethodWithEjb3() throws Exception {
|
||||
Method getAgeMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
Method getNameMethod = ITestBean.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute getAgeAttr = atas.getTransactionAttribute(getAgeMethod, Ejb3AnnotatedBean1.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, getAgeAttr.getPropagationBehavior());
|
||||
TransactionAttribute getNameAttr = atas.getTransactionAttribute(getNameMethod, Ejb3AnnotatedBean1.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_SUPPORTS, getNameAttr.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionAttributeDeclaredOnClassWithEjb3() throws Exception {
|
||||
Method getAgeMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
Method getNameMethod = ITestBean.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute getAgeAttr = atas.getTransactionAttribute(getAgeMethod, Ejb3AnnotatedBean2.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, getAgeAttr.getPropagationBehavior());
|
||||
TransactionAttribute getNameAttr = atas.getTransactionAttribute(getNameMethod, Ejb3AnnotatedBean2.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_SUPPORTS, getNameAttr.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionAttributeDeclaredOnInterfaceWithEjb3() throws Exception {
|
||||
Method getAgeMethod = ITestEjb.class.getMethod("getAge", (Class[]) null);
|
||||
Method getNameMethod = ITestEjb.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute getAgeAttr = atas.getTransactionAttribute(getAgeMethod, Ejb3AnnotatedBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, getAgeAttr.getPropagationBehavior());
|
||||
TransactionAttribute getNameAttr = atas.getTransactionAttribute(getNameMethod, Ejb3AnnotatedBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_SUPPORTS, getNameAttr.getPropagationBehavior());
|
||||
}
|
||||
|
||||
|
||||
public interface ITestBean {
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public interface ITestBean2 {
|
||||
|
||||
@Transactional
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public interface ITestBean3 {
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public static class Empty implements ITestBean {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public Empty() {
|
||||
}
|
||||
|
||||
public Empty(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean1 implements ITestBean, Serializable {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean1() {
|
||||
}
|
||||
|
||||
public TestBean1(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor=Exception.class)
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean2 implements ITestBean2 {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean2() {
|
||||
}
|
||||
|
||||
public TestBean2(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean3 implements ITestBean3 {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean3() {
|
||||
}
|
||||
|
||||
public TestBean3(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.REPEATABLE_READ, timeout=5,
|
||||
readOnly=true, rollbackFor=Exception.class, noRollbackFor={IOException.class})
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor=Exception.class, noRollbackFor={IOException.class})
|
||||
public static class TestBean4 implements ITestBean3 {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean4() {
|
||||
}
|
||||
|
||||
public TestBean4(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Transactional(rollbackFor=Exception.class, noRollbackFor={IOException.class})
|
||||
public @interface Tx {
|
||||
}
|
||||
|
||||
|
||||
@Tx
|
||||
public static class TestBean5 {
|
||||
|
||||
public int getAge() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean6 {
|
||||
|
||||
@Tx
|
||||
public int getAge() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static interface Foo<T> {
|
||||
|
||||
void doSomething(T theArgument);
|
||||
}
|
||||
|
||||
|
||||
public static class MyFoo implements Foo<String> {
|
||||
|
||||
@Transactional
|
||||
public void doSomething(String theArgument) {
|
||||
System.out.println(theArgument);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Ejb3AnnotatedBean1 implements ITestBean {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
@javax.ejb.TransactionAttribute(TransactionAttributeType.SUPPORTS)
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@javax.ejb.TransactionAttribute
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@javax.ejb.TransactionAttribute(TransactionAttributeType.SUPPORTS)
|
||||
public static class Ejb3AnnotatedBean2 implements ITestBean {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@javax.ejb.TransactionAttribute
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@javax.ejb.TransactionAttribute(TransactionAttributeType.SUPPORTS)
|
||||
public interface ITestEjb {
|
||||
|
||||
@javax.ejb.TransactionAttribute
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public static class Ejb3AnnotatedBean3 implements ITestEjb {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.annotation;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationTransactionInterceptorTests extends TestCase {
|
||||
|
||||
private CallCountingTransactionManager ptm;
|
||||
|
||||
private AnnotationTransactionAttributeSource source;
|
||||
|
||||
private TransactionInterceptor ti;
|
||||
|
||||
|
||||
public void setUp() {
|
||||
this.ptm = new CallCountingTransactionManager();
|
||||
this.source = new AnnotationTransactionAttributeSource();
|
||||
this.ti = new TransactionInterceptor(this.ptm, this.source);
|
||||
}
|
||||
|
||||
|
||||
public void testClassLevelOnly() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestClassLevelOnly());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestClassLevelOnly proxy = (TestClassLevelOnly) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testWithSingleMethodOverride() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithSingleMethodOverride());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithSingleMethodOverride proxy = (TestWithSingleMethodOverride) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingCompletelyElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testWithSingleMethodOverrideInverted() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithSingleMethodOverrideInverted());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithSingleMethodOverrideInverted proxy = (TestWithSingleMethodOverrideInverted) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingCompletelyElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testWithMultiMethodOverride() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithMultiMethodOverride());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithMultiMethodOverride proxy = (TestWithMultiMethodOverride) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingCompletelyElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
|
||||
public void testWithRollback() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithRollback());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithRollback proxy = (TestWithRollback) proxyFactory.getProxy();
|
||||
|
||||
try {
|
||||
proxy.doSomethingErroneous();
|
||||
fail("Should throw IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertGetTransactionAndRollbackCount(1);
|
||||
}
|
||||
|
||||
try {
|
||||
proxy.doSomethingElseErroneous();
|
||||
fail("Should throw IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertGetTransactionAndRollbackCount(2);
|
||||
}
|
||||
}
|
||||
|
||||
public void testWithInterface() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithInterfaceImpl());
|
||||
proxyFactory.addInterface(TestWithInterface.class);
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithInterface proxy = (TestWithInterface) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testCrossClassInterfaceMethodLevelOnJdkProxy() throws Exception {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new SomeServiceImpl());
|
||||
proxyFactory.addInterface(SomeService.class);
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
SomeService someService = (SomeService) proxyFactory.getProxy();
|
||||
|
||||
someService.bar();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
someService.foo();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
someService.fooBar();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
}
|
||||
|
||||
public void testCrossClassInterfaceOnJdkProxy() throws Exception {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new OtherServiceImpl());
|
||||
proxyFactory.addInterface(OtherService.class);
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
OtherService otherService = (OtherService) proxyFactory.getProxy();
|
||||
|
||||
otherService.foo();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
}
|
||||
|
||||
private void assertGetTransactionAndCommitCount(int expectedCount) {
|
||||
assertEquals(expectedCount, this.ptm.begun);
|
||||
assertEquals(expectedCount, this.ptm.commits);
|
||||
}
|
||||
|
||||
private void assertGetTransactionAndRollbackCount(int expectedCount) {
|
||||
assertEquals(expectedCount, this.ptm.begun);
|
||||
assertEquals(expectedCount, this.ptm.rollbacks);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class TestClassLevelOnly {
|
||||
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class TestWithSingleMethodOverride {
|
||||
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingCompletelyElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public static class TestWithSingleMethodOverrideInverted {
|
||||
|
||||
@Transactional
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingCompletelyElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class TestWithMultiMethodOverride {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingCompletelyElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor = IllegalStateException.class)
|
||||
public static class TestWithRollback {
|
||||
|
||||
public void doSomethingErroneous() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = IllegalArgumentException.class)
|
||||
public void doSomethingElseErroneous() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static interface TestWithInterface {
|
||||
|
||||
public void doSomething();
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomethingElse();
|
||||
}
|
||||
|
||||
|
||||
public static class TestWithInterfaceImpl implements TestWithInterface {
|
||||
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static interface SomeService {
|
||||
|
||||
void foo();
|
||||
|
||||
@Transactional
|
||||
void bar();
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
void fooBar();
|
||||
}
|
||||
|
||||
|
||||
public static class SomeServiceImpl implements SomeService {
|
||||
|
||||
public void bar() {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void foo() {
|
||||
}
|
||||
|
||||
@Transactional(readOnly = false)
|
||||
public void fooBar() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static interface OtherService {
|
||||
|
||||
void foo();
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class OtherServiceImpl implements OtherService {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.annotation;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationTransactionNamespaceHandlerTests extends TestCase {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
public void setUp() {
|
||||
this.context = new ClassPathXmlApplicationContext(
|
||||
"org/springframework/transaction/annotation/annotationTransactionNamespaceHandlerTests.xml");
|
||||
}
|
||||
|
||||
protected void tearDown() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
public void testIsProxy() throws Exception {
|
||||
TransactionalTestBean bean = getTestBean();
|
||||
assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
|
||||
Map services = this.context.getBeansWithAnnotation(Service.class);
|
||||
assertTrue("Stereotype annotation not visible", services.containsKey("testBean"));
|
||||
}
|
||||
|
||||
public void testInvokeTransactional() throws Exception {
|
||||
TransactionalTestBean testBean = getTestBean();
|
||||
CallCountingTransactionManager ptm = (CallCountingTransactionManager) context.getBean("transactionManager");
|
||||
|
||||
// try with transactional
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
testBean.findAllFoos();
|
||||
assertEquals("Should have 1 started transaction", 1, ptm.begun);
|
||||
assertEquals("Should have 1 committed transaction", 1, ptm.commits);
|
||||
|
||||
// try with non-transaction
|
||||
testBean.doSomething();
|
||||
assertEquals("Should not have started another transaction", 1, ptm.begun);
|
||||
|
||||
// try with exceptional
|
||||
try {
|
||||
testBean.exceptional(new IllegalArgumentException("foo"));
|
||||
fail("Should NEVER get here");
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
assertEquals("Should have another started transaction", 2, ptm.begun);
|
||||
assertEquals("Should have 1 rolled back transaction", 1, ptm.rollbacks);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testNonPublicMethodsNotAdvised() {
|
||||
TransactionalTestBean testBean = getTestBean();
|
||||
CallCountingTransactionManager ptm = (CallCountingTransactionManager) context.getBean("transactionManager");
|
||||
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
testBean.annotationsOnProtectedAreIgnored();
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
}
|
||||
|
||||
public void testMBeanExportAlsoWorks() throws Exception {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
assertEquals("done",
|
||||
server.invoke(ObjectName.getInstance("test:type=TestBean"), "doSomething", new Object[0], new String[0]));
|
||||
}
|
||||
|
||||
private TransactionalTestBean getTestBean() {
|
||||
return (TransactionalTestBean) context.getBean("testBean");
|
||||
}
|
||||
|
||||
|
||||
@Service
|
||||
@ManagedResource("test:type=TestBean")
|
||||
public static class TransactionalTestBean {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Collection findAllFoos() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveFoo() {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
throw t;
|
||||
}
|
||||
|
||||
@ManagedOperation
|
||||
public String doSomething() {
|
||||
return "done";
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected void annotationsOnProtectedAreIgnored() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests.TransactionalTestBean;
|
||||
|
||||
/**
|
||||
* Tests demonstrating use of @EnableTransactionManagement @Configuration classes.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class EnableTransactionManagementTests {
|
||||
|
||||
@Test
|
||||
public void transactionProxyIsCreated() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(EnableTxConfig.class, TxManagerConfig.class);
|
||||
ctx.refresh();
|
||||
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
|
||||
assertThat("testBean is not a proxy", AopUtils.isAopProxy(bean), is(true));
|
||||
Map<?,?> services = ctx.getBeansWithAnnotation(Service.class);
|
||||
assertThat("Stereotype annotation not visible", services.containsKey("testBean"), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txManagerIsResolvedOnInvocationOfTransactionalMethod() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(EnableTxConfig.class, TxManagerConfig.class);
|
||||
ctx.refresh();
|
||||
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
|
||||
|
||||
// invoke a transactional method, causing the PlatformTransactionManager bean to be resolved.
|
||||
bean.findAllFoos();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txManagerIsResolvedCorrectlyWhenMultipleManagersArePresent() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(EnableTxConfig.class, MultiTxManagerConfig.class);
|
||||
ctx.refresh();
|
||||
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
|
||||
|
||||
// invoke a transactional method, causing the PlatformTransactionManager bean to be resolved.
|
||||
bean.findAllFoos();
|
||||
}
|
||||
|
||||
/**
|
||||
* A cheap test just to prove that in ASPECTJ mode, the AnnotationTransactionAspect does indeed
|
||||
* get loaded -- or in this case, attempted to be loaded at which point the test fails.
|
||||
*/
|
||||
@Test
|
||||
public void proxyTypeAspectJCausesRegistrationOfAnnotationTransactionAspect() {
|
||||
try {
|
||||
new AnnotationConfigApplicationContext(EnableAspectJTxConfig.class, TxManagerConfig.class);
|
||||
fail("should have thrown CNFE when trying to load AnnotationTransactionAspect. " +
|
||||
"Do you actually have org.springframework.aspects on the classpath?");
|
||||
} catch (Exception ex) {
|
||||
System.out.println(ex);
|
||||
assertThat(ex.getMessage().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist"), is(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class EnableTxConfig {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
|
||||
static class EnableAspectJTxConfig {
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class TxManagerConfig {
|
||||
|
||||
@Bean
|
||||
public TransactionalTestBean testBean() {
|
||||
return new TransactionalTestBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class MultiTxManagerConfig extends TxManagerConfig implements TransactionManagementConfigurer {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager2() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
public PlatformTransactionManager annotationDrivenTransactionManager() {
|
||||
return txManager2();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
|
||||
|
||||
<tx:annotation-driven/>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.transaction.CallCountingTransactionManager"/>
|
||||
|
||||
<bean id="testBean"
|
||||
class="org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests$TransactionalTestBean"/>
|
||||
|
||||
<context:mbean-export/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationDrivenTests extends TestCase {
|
||||
|
||||
public void testWithProxyTargetClass() throws Exception {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("annotationDrivenProxyTargetClassTests.xml", getClass());
|
||||
doTestWithMultipleTransactionManagers(context);
|
||||
}
|
||||
|
||||
public void testWithConfigurationClass() throws Exception {
|
||||
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
|
||||
parent.register(TransactionManagerConfiguration.class);
|
||||
parent.refresh();
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"annotationDrivenConfigurationClassTests.xml"}, getClass(), parent);
|
||||
doTestWithMultipleTransactionManagers(context);
|
||||
}
|
||||
|
||||
private void doTestWithMultipleTransactionManagers(ApplicationContext context) {
|
||||
CallCountingTransactionManager tm1 = context.getBean("transactionManager1", CallCountingTransactionManager.class);
|
||||
CallCountingTransactionManager tm2 = context.getBean("transactionManager2", CallCountingTransactionManager.class);
|
||||
TransactionalService service = context.getBean("service", TransactionalService.class);
|
||||
assertTrue(AopUtils.isCglibProxy(service));
|
||||
service.setSomething("someName");
|
||||
assertEquals(1, tm1.commits);
|
||||
assertEquals(0, tm2.commits);
|
||||
service.doSomething();
|
||||
assertEquals(1, tm1.commits);
|
||||
assertEquals(1, tm2.commits);
|
||||
service.setSomething("someName");
|
||||
assertEquals(2, tm1.commits);
|
||||
assertEquals(1, tm2.commits);
|
||||
service.doSomething();
|
||||
assertEquals(2, tm1.commits);
|
||||
assertEquals(2, tm2.commits);
|
||||
}
|
||||
|
||||
public void testSerializableWithPreviousUsage() throws Exception {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("annotationDrivenProxyTargetClassTests.xml", getClass());
|
||||
TransactionalService service = context.getBean("service", TransactionalService.class);
|
||||
service.setSomething("someName");
|
||||
service = (TransactionalService) SerializationTestUtils.serializeAndDeserialize(service);
|
||||
service.setSomething("someName");
|
||||
}
|
||||
|
||||
public void testSerializableWithoutPreviousUsage() throws Exception {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("annotationDrivenProxyTargetClassTests.xml", getClass());
|
||||
TransactionalService service = context.getBean("service", TransactionalService.class);
|
||||
service = (TransactionalService) SerializationTestUtils.serializeAndDeserialize(service);
|
||||
service.setSomething("someName");
|
||||
}
|
||||
|
||||
|
||||
public static class TransactionCheckingInterceptor implements MethodInterceptor, Serializable {
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
if (methodInvocation.getMethod().getName().equals("setSomething")) {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
else {
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
return methodInvocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@Configuration
|
||||
public class TransactionManagerConfiguration {
|
||||
|
||||
@Bean
|
||||
@Qualifier("synch")
|
||||
public PlatformTransactionManager transactionManager1() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Qualifier("noSynch")
|
||||
public PlatformTransactionManager transactionManager2() {
|
||||
CallCountingTransactionManager tm = new CallCountingTransactionManager();
|
||||
tm.setTransactionSynchronization(CallCountingTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
return tm;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class TransactionalService implements Serializable {
|
||||
|
||||
@Transactional("synch")
|
||||
public void setSomething(String name) {
|
||||
}
|
||||
|
||||
@Transactional("noSynch")
|
||||
public void doSomething() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
|
||||
<tx:annotation-driven proxy-target-class="true" order="0"/>
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor advice-ref="txCheckingInterceptor" pointcut="execution(* *..TransactionalService.*(..))" order="1"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="txCheckingInterceptor" class="org.springframework.transaction.config.AnnotationDrivenTests$TransactionCheckingInterceptor"/>
|
||||
|
||||
<bean id="service" class="org.springframework.transaction.config.TransactionalService"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
|
||||
<tx:annotation-driven proxy-target-class="true" order="0"/>
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor advice-ref="txCheckingInterceptor" pointcut="execution(* *..TransactionalService.*(..))" order="1"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="txCheckingInterceptor" class="org.springframework.transaction.config.AnnotationDrivenTests$TransactionCheckingInterceptor"/>
|
||||
|
||||
<bean id="transactionManager1" class="org.springframework.transaction.CallCountingTransactionManager">
|
||||
<qualifier value="synch"/>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager2" class="org.springframework.transaction.CallCountingTransactionManager">
|
||||
<property name="transactionSynchronizationName" value="SYNCHRONIZATION_NEVER"/>
|
||||
<qualifier value="noSynch"/>
|
||||
</bean>
|
||||
|
||||
<bean id="service" class="org.springframework.transaction.config.TransactionalService"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.MockCallbackPreferringTransactionManager;
|
||||
import org.springframework.transaction.NoTransactionException;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.UnexpectedRollbackException;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo;
|
||||
|
||||
/**
|
||||
* Mock object based tests for transaction aspects.
|
||||
* True unit test in that it tests how the transaction aspect uses
|
||||
* the PlatformTransactionManager helper, rather than indirectly
|
||||
* testing the helper implementation.
|
||||
*
|
||||
* This is a superclass to allow testing both the AOP Alliance MethodInterceptor
|
||||
* and the AspectJ aspect.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 16.03.2003
|
||||
*/
|
||||
public abstract class AbstractTransactionAspectTests extends TestCase {
|
||||
|
||||
protected Method exceptionalMethod;
|
||||
|
||||
protected Method getNameMethod;
|
||||
|
||||
protected Method setNameMethod;
|
||||
|
||||
|
||||
public AbstractTransactionAspectTests() {
|
||||
try {
|
||||
// Cache the methods we'll be testing
|
||||
exceptionalMethod = ITestBean.class.getMethod("exceptional", new Class[] { Throwable.class });
|
||||
getNameMethod = ITestBean.class.getMethod("getName", (Class[]) null);
|
||||
setNameMethod = ITestBean.class.getMethod("setName", new Class[] { String.class} );
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new RuntimeException("Shouldn't happen", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testNoTransaction() throws Exception {
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
|
||||
// expect no calls
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
TransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
|
||||
// All the methods in this class use the advised() template method
|
||||
// to obtain a transaction object, configured with the given PlatformTransactionManager
|
||||
// and transaction attribute source
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a transaction is created and committed.
|
||||
*/
|
||||
public void testTransactionShouldSucceed() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(getNameMethod, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a transaction is created and committed using
|
||||
* CallbackPreferringPlatformTransactionManager.
|
||||
*/
|
||||
public void testTransactionShouldSucceedWithCallbackPreference() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(getNameMethod, txatt);
|
||||
|
||||
MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
assertSame(txatt, ptm.getDefinition());
|
||||
assertFalse(ptm.getStatus().isRollbackOnly());
|
||||
}
|
||||
|
||||
public void testTransactionExceptionPropagatedWithCallbackPreference() throws Throwable {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(exceptionalMethod, txatt);
|
||||
|
||||
MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
try {
|
||||
itb.exceptional(new OptimisticLockingFailureException(""));
|
||||
fail("Should have thrown OptimisticLockingFailureException");
|
||||
}
|
||||
catch (OptimisticLockingFailureException ex) {
|
||||
// expected
|
||||
}
|
||||
checkTransactionStatus(false);
|
||||
|
||||
assertSame(txatt, ptm.getDefinition());
|
||||
assertFalse(ptm.getStatus().isRollbackOnly());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that two transactions are created and committed.
|
||||
*/
|
||||
public void testTwoTransactionsShouldSucceed() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas1 = new MapTransactionAttributeSource();
|
||||
tas1.register(getNameMethod, txatt);
|
||||
MapTransactionAttributeSource tas2 = new MapTransactionAttributeSource();
|
||||
tas2.register(setNameMethod, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 2);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(2);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, new TransactionAttributeSource[] {tas1, tas2});
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
itb.setName("myName");
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a transaction is created and committed.
|
||||
*/
|
||||
public void testTransactionShouldSucceedWithNotNew() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(getNameMethod, txatt);
|
||||
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
TransactionStatus status = (TransactionStatus) statusControl.getMock();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
// verification!?
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testEnclosingTransactionWithNonTransactionMethodOnAdvisedInside() throws Throwable {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(exceptionalMethod, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
final String spouseName = "innerName";
|
||||
|
||||
TestBean outer = new TestBean() {
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
assertTrue(ti.hasTransaction());
|
||||
assertEquals(spouseName, getSpouse().getName());
|
||||
}
|
||||
};
|
||||
TestBean inner = new TestBean() {
|
||||
public String getName() {
|
||||
// Assert that we're in the inner proxy
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
assertFalse(ti.hasTransaction());
|
||||
return spouseName;
|
||||
}
|
||||
};
|
||||
|
||||
ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
|
||||
ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
|
||||
outer.setSpouse(innerProxy);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
// Will invoke inner.getName, which is non-transactional
|
||||
outerProxy.exceptional(null);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testEnclosingTransactionWithNestedTransactionOnAdvisedInside() throws Throwable {
|
||||
final TransactionAttribute outerTxatt = new DefaultTransactionAttribute();
|
||||
final TransactionAttribute innerTxatt = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_NESTED);
|
||||
|
||||
Method outerMethod = exceptionalMethod;
|
||||
Method innerMethod = getNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(outerMethod, outerTxatt);
|
||||
tas.register(innerMethod, innerTxatt);
|
||||
|
||||
TransactionStatus outerStatus = transactionStatusForNewTransaction();
|
||||
TransactionStatus innerStatus = transactionStatusForNewTransaction();
|
||||
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect a transaction
|
||||
ptm.getTransaction(outerTxatt);
|
||||
ptmControl.setReturnValue(outerStatus, 1);
|
||||
|
||||
ptm.getTransaction(innerTxatt);
|
||||
ptmControl.setReturnValue(innerStatus, 1);
|
||||
|
||||
ptm.commit(innerStatus);
|
||||
ptmControl.setVoidCallable(1);
|
||||
|
||||
ptm.commit(outerStatus);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
final String spouseName = "innerName";
|
||||
|
||||
TestBean outer = new TestBean() {
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
assertTrue(ti.hasTransaction());
|
||||
assertEquals(outerTxatt, ti.getTransactionAttribute());
|
||||
assertEquals(spouseName, getSpouse().getName());
|
||||
}
|
||||
};
|
||||
TestBean inner = new TestBean() {
|
||||
public String getName() {
|
||||
// Assert that we're in the inner proxy
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
// Has nested transaction
|
||||
assertTrue(ti.hasTransaction());
|
||||
assertEquals(innerTxatt, ti.getTransactionAttribute());
|
||||
return spouseName;
|
||||
}
|
||||
};
|
||||
|
||||
ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
|
||||
ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
|
||||
outer.setSpouse(innerProxy);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
// Will invoke inner.getName, which is non-transactional
|
||||
outerProxy.exceptional(null);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testRollbackOnCheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), true, false);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnCheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), false, false);
|
||||
}
|
||||
|
||||
public void testRollbackOnUncheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), true, false);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnUncheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), false, false);
|
||||
}
|
||||
|
||||
public void testRollbackOnCheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), true, true);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnCheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), false, true);
|
||||
}
|
||||
|
||||
public void testRollbackOnUncheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), true, true);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnUncheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given exception thrown by the target can produce the
|
||||
* desired behavior with the appropriate transaction attribute.
|
||||
* @param ex exception to be thrown by the target
|
||||
* @param shouldRollback whether this should cause a transaction rollback
|
||||
*/
|
||||
protected void doTestRollbackOnException(
|
||||
final Exception ex, final boolean shouldRollback, boolean rollbackException) throws Exception {
|
||||
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute() {
|
||||
public boolean rollbackOn(Throwable t) {
|
||||
assertTrue(t == ex);
|
||||
return shouldRollback;
|
||||
}
|
||||
};
|
||||
|
||||
Method m = exceptionalMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
TransactionStatus status = (TransactionStatus) statusControl.getMock();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Gets additional call(s) from TransactionControl
|
||||
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
|
||||
if (shouldRollback) {
|
||||
ptm.rollback(status);
|
||||
}
|
||||
else {
|
||||
ptm.commit(status);
|
||||
}
|
||||
TransactionSystemException tex = new TransactionSystemException("system exception");
|
||||
if (rollbackException) {
|
||||
ptmControl.setThrowable(tex, 1);
|
||||
}
|
||||
else {
|
||||
ptmControl.setVoidCallable(1);
|
||||
}
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
try {
|
||||
itb.exceptional(ex);
|
||||
fail("Should have thrown exception");
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (rollbackException) {
|
||||
assertEquals("Caught wrong exception", tex, t );
|
||||
}
|
||||
else {
|
||||
assertEquals("Caught wrong exception", ex, t);
|
||||
}
|
||||
}
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that TransactionStatus.setRollbackOnly works.
|
||||
*/
|
||||
public void testProgrammaticRollback() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
Method m = getNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
final String name = "jenny";
|
||||
TestBean tb = new TestBean() {
|
||||
public String getName() {
|
||||
TransactionStatus txStatus = TransactionInterceptor.currentTransactionStatus();
|
||||
txStatus.setRollbackOnly();
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
// verification!?
|
||||
assertTrue(name.equals(itb.getName()));
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a TransactionStatus object configured for a new transaction
|
||||
*/
|
||||
private TransactionStatus transactionStatusForNewTransaction() {
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
return (TransactionStatus) statusControl.getMock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate a transaction infrastructure failure.
|
||||
* Shouldn't invoke target method.
|
||||
*/
|
||||
public void testCannotCreateTransaction() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
Method m = getNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
CannotCreateTransactionException ex = new CannotCreateTransactionException("foobar", null);
|
||||
ptmControl.setThrowable(ex);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean() {
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException(
|
||||
"Shouldn't have invoked target method when couldn't create transaction for transactional method");
|
||||
}
|
||||
};
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
try {
|
||||
itb.getName();
|
||||
fail("Shouldn't have invoked method");
|
||||
}
|
||||
catch (CannotCreateTransactionException thrown) {
|
||||
assertTrue(thrown == ex);
|
||||
}
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate failure of the underlying transaction infrastructure to commit.
|
||||
* Check that the target method was invoked, but that the transaction
|
||||
* infrastructure exception was thrown to the client
|
||||
*/
|
||||
public void testCannotCommitTransaction() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
Method m = setNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
Method m2 = getNameMethod;
|
||||
// No attributes for m2
|
||||
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status);
|
||||
UnexpectedRollbackException ex = new UnexpectedRollbackException("foobar", null);
|
||||
ptm.commit(status);
|
||||
ptmControl.setThrowable(ex);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
String name = "new name";
|
||||
try {
|
||||
itb.setName(name);
|
||||
fail("Shouldn't have succeeded");
|
||||
}
|
||||
catch (UnexpectedRollbackException thrown) {
|
||||
assertTrue(thrown == ex);
|
||||
}
|
||||
|
||||
// Should have invoked target and changed name
|
||||
assertTrue(itb.getName() == name);
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
protected void checkTransactionStatus(boolean expected) {
|
||||
try {
|
||||
TransactionInterceptor.currentTransactionStatus();
|
||||
if (!expected) {
|
||||
fail("Should have thrown NoTransactionException");
|
||||
}
|
||||
}
|
||||
catch (NoTransactionException ex) {
|
||||
if (expected) {
|
||||
fail("Should have current TransactionStatus");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Object advised(
|
||||
Object target, PlatformTransactionManager ptm, TransactionAttributeSource[] tas) throws Exception {
|
||||
|
||||
return advised(target, ptm, new CompositeTransactionAttributeSource(tas));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this to create an advised object based on the
|
||||
* given target. In the case of AspectJ, the advised object will already
|
||||
* have been created, as there's no distinction between target and proxy.
|
||||
* In the case of Spring's own AOP framework, a proxy must be created
|
||||
* using a suitably configured transaction interceptor
|
||||
* @param target target if there's a distinct target. If not (AspectJ),
|
||||
* return target.
|
||||
* @return transactional advised object
|
||||
*/
|
||||
protected abstract Object advised(
|
||||
Object target, PlatformTransactionManager ptm, TransactionAttributeSource tas) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcut;
|
||||
import org.springframework.aop.target.HotSwappableTargetSource;
|
||||
import org.springframework.beans.DerivedTestBean;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
||||
/**
|
||||
* Test cases for AOP transaction management.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 23.04.2003
|
||||
*/
|
||||
public class BeanFactoryTransactionTests extends TestCase {
|
||||
|
||||
private XmlBeanFactory factory;
|
||||
|
||||
public void setUp() {
|
||||
this.factory = new XmlBeanFactory(new ClassPathResource("transactionalBeanFactory.xml", getClass()));
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory1() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory1");
|
||||
assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass()));
|
||||
doTestGetsAreNotTransactional(testBean);
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory2DynamicProxy() throws NoSuchMethodException {
|
||||
this.factory.preInstantiateSingletons();
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2DynamicProxy");
|
||||
assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass()));
|
||||
doTestGetsAreNotTransactional(testBean);
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory2Cglib() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Cglib");
|
||||
assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(testBean));
|
||||
doTestGetsAreNotTransactional(testBean);
|
||||
}
|
||||
|
||||
public void testProxyFactory2Lazy() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Lazy");
|
||||
assertFalse(factory.containsSingleton("target"));
|
||||
assertEquals(666, testBean.getAge());
|
||||
assertTrue(factory.containsSingleton("target"));
|
||||
}
|
||||
|
||||
public void testCglibTransactionProxyImplementsNoInterfaces() throws NoSuchMethodException {
|
||||
ImplementsNoInterfaces ini = (ImplementsNoInterfaces) factory.getBean("cglibNoInterfaces");
|
||||
assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(ini));
|
||||
String newName = "Gordon";
|
||||
|
||||
// Install facade
|
||||
CallCountingTransactionManager ptm = new CallCountingTransactionManager();
|
||||
PlatformTransactionManagerFacade.delegate = ptm;
|
||||
|
||||
ini.setName(newName);
|
||||
assertEquals(newName, ini.getName());
|
||||
assertEquals(2, ptm.commits);
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory3() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory3");
|
||||
assertTrue("testBean is a full proxy", testBean instanceof DerivedTestBean);
|
||||
InvocationCounterPointcut txnCounter = (InvocationCounterPointcut) factory.getBean("txnInvocationCounterPointcut");
|
||||
InvocationCounterInterceptor preCounter = (InvocationCounterInterceptor) factory.getBean("preInvocationCounterInterceptor");
|
||||
InvocationCounterInterceptor postCounter = (InvocationCounterInterceptor) factory.getBean("postInvocationCounterInterceptor");
|
||||
txnCounter.counter = 0;
|
||||
preCounter.counter = 0;
|
||||
postCounter.counter = 0;
|
||||
doTestGetsAreNotTransactional(testBean);
|
||||
// Can't assert it's equal to 4 as the pointcut may be optimized and only invoked once
|
||||
assertTrue(0 < txnCounter.counter && txnCounter.counter <= 4);
|
||||
assertEquals(4, preCounter.counter);
|
||||
assertEquals(4, postCounter.counter);
|
||||
}
|
||||
|
||||
private void doTestGetsAreNotTransactional(final ITestBean testBean) {
|
||||
// Install facade
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect no methods
|
||||
ptmControl.replay();
|
||||
PlatformTransactionManagerFacade.delegate = ptm;
|
||||
|
||||
assertTrue("Age should not be " + testBean.getAge(), testBean.getAge() == 666);
|
||||
// Check no calls
|
||||
ptmControl.verify();
|
||||
|
||||
// Install facade expecting a call
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
final TransactionStatus ts = (TransactionStatus) statusControl.getMock();
|
||||
ptm = new PlatformTransactionManager() {
|
||||
private boolean invoked;
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
|
||||
if (invoked) {
|
||||
throw new IllegalStateException("getTransaction should not get invoked more than once");
|
||||
}
|
||||
invoked = true;
|
||||
System.out.println(definition.getName());
|
||||
if (!((definition.getName().indexOf(TestBean.class.getName()) != -1) &&
|
||||
(definition.getName().indexOf("setAge") != -1))) {
|
||||
throw new IllegalStateException(
|
||||
"transaction name should contain class and method name: " + definition.getName());
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
public void commit(TransactionStatus status) throws TransactionException {
|
||||
assertTrue(status == ts);
|
||||
}
|
||||
public void rollback(TransactionStatus status) throws TransactionException {
|
||||
throw new IllegalStateException("rollback should not get invoked");
|
||||
}
|
||||
};
|
||||
PlatformTransactionManagerFacade.delegate = ptm;
|
||||
|
||||
// TODO same as old age to avoid ordering effect for now
|
||||
int age = 666;
|
||||
testBean.setAge(age);
|
||||
assertTrue(testBean.getAge() == age);
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testGetBeansOfTypeWithAbstract() {
|
||||
Map beansOfType = factory.getBeansOfType(ITestBean.class, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we fail gracefully if the user doesn't set any transaction attributes.
|
||||
*/
|
||||
public void testNoTransactionAttributeSource() {
|
||||
try {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("noTransactionAttributeSource.xml", getClass()));
|
||||
ITestBean testBean = (ITestBean) bf.getBean("noTransactionAttributeSource");
|
||||
fail("Should require TransactionAttributeSource to be set");
|
||||
}
|
||||
catch (FatalBeanException ex) {
|
||||
// Ok
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we can set the target to a dynamic TargetSource.
|
||||
*/
|
||||
public void testDynamicTargetSource() throws NoSuchMethodException {
|
||||
// Install facade
|
||||
CallCountingTransactionManager txMan = new CallCountingTransactionManager();
|
||||
PlatformTransactionManagerFacade.delegate = txMan;
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("hotSwapped");
|
||||
assertEquals(666, tb.getAge());
|
||||
int newAge = 557;
|
||||
tb.setAge(newAge);
|
||||
assertEquals(newAge, tb.getAge());
|
||||
|
||||
TestBean target2 = new TestBean();
|
||||
target2.setAge(65);
|
||||
HotSwappableTargetSource ts = (HotSwappableTargetSource) factory.getBean("swapper");
|
||||
ts.swap(target2);
|
||||
assertEquals(target2.getAge(), tb.getAge());
|
||||
tb.setAge(newAge);
|
||||
assertEquals(newAge, target2.getAge());
|
||||
|
||||
assertEquals(0, txMan.inflight);
|
||||
assertEquals(2, txMan.commits);
|
||||
assertEquals(0, txMan.rollbacks);
|
||||
}
|
||||
|
||||
|
||||
public static class InvocationCounterPointcut extends StaticMethodMatcherPointcut {
|
||||
|
||||
int counter = 0;
|
||||
|
||||
public boolean matches(Method method, Class clazz) {
|
||||
counter++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class InvocationCounterInterceptor implements MethodInterceptor {
|
||||
|
||||
int counter = 0;
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
counter++;
|
||||
return methodInvocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import org.springframework.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Test for CGLIB proxying that implements no interfaces
|
||||
* and has one dependency.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class ImplementsNoInterfaces {
|
||||
|
||||
private TestBean testBean;
|
||||
|
||||
public void setDependency(TestBean testBean) {
|
||||
this.testBean = testBean;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return testBean.getName();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
testBean.setName(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Inherits fallback behavior from AbstractFallbackTransactionAttributeSource.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class MapTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource {
|
||||
|
||||
private final Map<Object, TransactionAttribute> attributeMap = new HashMap<Object, TransactionAttribute>();
|
||||
|
||||
|
||||
public void register(Method method, TransactionAttribute txAtt) {
|
||||
this.attributeMap.put(method, txAtt);
|
||||
}
|
||||
|
||||
public void register(Class clazz, TransactionAttribute txAtt) {
|
||||
this.attributeMap.put(clazz, txAtt);
|
||||
}
|
||||
|
||||
|
||||
protected TransactionAttribute findTransactionAttribute(Method method) {
|
||||
return this.attributeMap.get(method);
|
||||
}
|
||||
|
||||
protected TransactionAttribute findTransactionAttribute(Class clazz) {
|
||||
return this.attributeMap.get(clazz);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
/**
|
||||
* An example {@link RuntimeException} for use in testing rollback rules.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class MyRuntimeException extends NestedRuntimeException {
|
||||
public MyRuntimeException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
||||
/**
|
||||
* Used for testing only (for example, when we must replace the
|
||||
* behavior of a PlatformTransactionManager bean we don't have access to).
|
||||
*
|
||||
* <p>Allows behavior of an entire class to change with static delegate change.
|
||||
* Not multi-threaded.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 26.04.2003
|
||||
*/
|
||||
public class PlatformTransactionManagerFacade implements PlatformTransactionManager {
|
||||
|
||||
/**
|
||||
* This member can be changed to change behavior class-wide.
|
||||
*/
|
||||
public static PlatformTransactionManager delegate;
|
||||
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) {
|
||||
return delegate.getTransaction(definition);
|
||||
}
|
||||
|
||||
public void commit(TransactionStatus status) {
|
||||
delegate.commit(status);
|
||||
}
|
||||
|
||||
public void rollback(TransactionStatus status) {
|
||||
delegate.rollback(status);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link RollbackRuleAttribute} class.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 09.04.2003
|
||||
*/
|
||||
public class RollbackRuleTests extends TestCase {
|
||||
|
||||
public void testFoundImmediatelyWithString() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.lang.Exception.class.getName());
|
||||
assertTrue(rr.getDepth(new Exception()) == 0);
|
||||
}
|
||||
|
||||
public void testFoundImmediatelyWithClass() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(Exception.class);
|
||||
assertTrue(rr.getDepth(new Exception()) == 0);
|
||||
}
|
||||
|
||||
public void testNotFound() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.io.IOException.class.getName());
|
||||
assertTrue(rr.getDepth(new MyRuntimeException("")) == -1);
|
||||
}
|
||||
|
||||
public void testAncestry() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.lang.Exception.class.getName());
|
||||
// Exception -> Runtime -> NestedRuntime -> MyRuntimeException
|
||||
assertThat(rr.getDepth(new MyRuntimeException("")), equalTo(3));
|
||||
}
|
||||
|
||||
public void testAlwaysTrueForThrowable() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.lang.Throwable.class.getName());
|
||||
assertTrue(rr.getDepth(new MyRuntimeException("")) > 0);
|
||||
assertTrue(rr.getDepth(new IOException()) > 0);
|
||||
assertTrue(rr.getDepth(new FatalBeanException(null,null)) > 0);
|
||||
assertTrue(rr.getDepth(new RuntimeException()) > 0);
|
||||
}
|
||||
|
||||
public void testCtorArgMustBeAThrowableClassWithNonThrowableType() {
|
||||
try {
|
||||
new RollbackRuleAttribute(StringBuffer.class);
|
||||
fail("Cannot construct a RollbackRuleAttribute with a non-Throwable type");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorArgMustBeAThrowableClassWithNullThrowableType() {
|
||||
try {
|
||||
new RollbackRuleAttribute((Class) null);
|
||||
fail("Cannot construct a RollbackRuleAttribute with a null-Throwable type");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorArgExceptionStringNameVersionWithNull() {
|
||||
try {
|
||||
new RollbackRuleAttribute((String) null);
|
||||
fail("Cannot construct a RollbackRuleAttribute with a null-Throwable type");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 09.04.2003
|
||||
*/
|
||||
public class RuleBasedTransactionAttributeTests {
|
||||
|
||||
@Test
|
||||
public void testDefaultRule() {
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute();
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
assertTrue(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test one checked exception that should roll back.
|
||||
*/
|
||||
@Test
|
||||
public void testRuleForRollbackOnChecked() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new RollbackRuleAttribute(IOException.class.getName()));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
assertTrue(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertTrue(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleForCommitOnUnchecked() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute(MyRuntimeException.class.getName()));
|
||||
list.add(new RollbackRuleAttribute(IOException.class.getName()));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
// Check default behaviour is overridden
|
||||
assertFalse(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertTrue(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleForSelectiveRollbackOnCheckedWithString() {
|
||||
List<RollbackRuleAttribute> l = new LinkedList<RollbackRuleAttribute>();
|
||||
l.add(new RollbackRuleAttribute(java.rmi.RemoteException.class.getName()));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, l);
|
||||
doTestRuleForSelectiveRollbackOnChecked(rta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleForSelectiveRollbackOnCheckedWithClass() {
|
||||
List<RollbackRuleAttribute> l = Collections.singletonList(new RollbackRuleAttribute(RemoteException.class));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, l);
|
||||
doTestRuleForSelectiveRollbackOnChecked(rta);
|
||||
}
|
||||
|
||||
private void doTestRuleForSelectiveRollbackOnChecked(RuleBasedTransactionAttribute rta) {
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
// Check default behaviour is overridden
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertTrue(rta.rollbackOn(new RemoteException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a rule can cause commit on a IOException
|
||||
* when Exception prompts a rollback.
|
||||
*/
|
||||
@Test
|
||||
public void testRuleForCommitOnSubclassOfChecked() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
// Note that it's important to ensure that we have this as
|
||||
// a FQN: otherwise it will match everything!
|
||||
list.add(new RollbackRuleAttribute("java.lang.Exception"));
|
||||
list.add(new NoRollbackRuleAttribute("IOException"));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
assertTrue(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackNever() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute("Throwable"));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertFalse(rta.rollbackOn(new Throwable()));
|
||||
assertFalse(rta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringMatchesEditor() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute("Throwable"));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
TransactionAttributeEditor tae = new TransactionAttributeEditor();
|
||||
tae.setAsText(rta.toString());
|
||||
rta = (RuleBasedTransactionAttribute) tae.getValue();
|
||||
|
||||
assertFalse(rta.rollbackOn(new Throwable()));
|
||||
assertFalse(rta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* See <a href="http://forum.springframework.org/showthread.php?t=41350">this forum post</a>.
|
||||
*/
|
||||
@Test
|
||||
public void testConflictingRulesToDetermineExactContract() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute(MyBusinessWarningException.class));
|
||||
list.add(new RollbackRuleAttribute(MyBusinessException.class));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new MyBusinessException()));
|
||||
assertFalse(rta.rollbackOn(new MyBusinessWarningException()));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class MyBusinessException extends Exception {}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static final class MyBusinessWarningException extends MyBusinessException {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* Tests to check conversion from String to TransactionAttribute.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 26.04.2003
|
||||
*/
|
||||
public class TransactionAttributeEditorTests {
|
||||
|
||||
@Test
|
||||
public void testNull() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText(null);
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta == null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyString() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta == null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeOnly() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("PROPAGATION_REQUIRED");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta != null);
|
||||
assertTrue(ta.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_DEFAULT);
|
||||
assertTrue(!ta.isReadOnly());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidPropagationCodeOnly() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
// should have failed with bogus propagation code
|
||||
pe.setAsText("XXPROPAGATION_REQUIRED");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeAndIsolationCode() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("PROPAGATION_REQUIRED, ISOLATION_READ_UNCOMMITTED");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta != null);
|
||||
assertTrue(ta.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testValidPropagationAndIsolationCodesAndInvalidRollbackRule() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
// should fail with bogus rollback rule
|
||||
pe.setAsText("PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED,XXX");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeAndIsolationCodeAndRollbackRules1() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("PROPAGATION_MANDATORY,ISOLATION_REPEATABLE_READ,timeout_10,-IOException,+MyRuntimeException");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertNotNull(ta);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertEquals(ta.getTimeout(), 10);
|
||||
assertFalse(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(ta.rollbackOn(new Exception()));
|
||||
// Check for our bizarre customized rollback rules
|
||||
assertTrue(ta.rollbackOn(new IOException()));
|
||||
assertTrue(!ta.rollbackOn(new MyRuntimeException("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeAndIsolationCodeAndRollbackRules2() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("+IOException,readOnly,ISOLATION_READ_COMMITTED,-MyRuntimeException,PROPAGATION_SUPPORTS");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertNotNull(ta);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_READ_COMMITTED);
|
||||
assertEquals(ta.getTimeout(), TransactionDefinition.TIMEOUT_DEFAULT);
|
||||
assertTrue(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(ta.rollbackOn(new Exception()));
|
||||
// Check for our bizarre customized rollback rules
|
||||
assertFalse(ta.rollbackOn(new IOException()));
|
||||
assertTrue(ta.rollbackOn(new MyRuntimeException("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultTransactionAttributeToString() {
|
||||
DefaultTransactionAttribute source = new DefaultTransactionAttribute();
|
||||
source.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
source.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
source.setTimeout(10);
|
||||
source.setReadOnly(true);
|
||||
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText(source.toString());
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertEquals(ta, source);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertEquals(ta.getTimeout(), 10);
|
||||
assertTrue(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(ta.rollbackOn(new Exception()));
|
||||
|
||||
source.setTimeout(9);
|
||||
assertNotSame(ta, source);
|
||||
source.setTimeout(10);
|
||||
assertEquals(ta, source);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleBasedTransactionAttributeToString() {
|
||||
RuleBasedTransactionAttribute source = new RuleBasedTransactionAttribute();
|
||||
source.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
source.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
source.setTimeout(10);
|
||||
source.setReadOnly(true);
|
||||
source.getRollbackRules().add(new RollbackRuleAttribute("IllegalArgumentException"));
|
||||
source.getRollbackRules().add(new NoRollbackRuleAttribute("IllegalStateException"));
|
||||
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText(source.toString());
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertEquals(ta, source);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertEquals(ta.getTimeout(), 10);
|
||||
assertTrue(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new IllegalArgumentException()));
|
||||
assertFalse(ta.rollbackOn(new IllegalStateException()));
|
||||
|
||||
source.getRollbackRules().clear();
|
||||
assertNotSame(ta, source);
|
||||
source.getRollbackRules().add(new RollbackRuleAttribute("IllegalArgumentException"));
|
||||
source.getRollbackRules().add(new NoRollbackRuleAttribute("IllegalStateException"));
|
||||
assertEquals(ta, source);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class TransactionAttributeSourceAdvisorTests extends TestCase {
|
||||
|
||||
public TransactionAttributeSourceAdvisorTests(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public void testSerializability() throws Exception {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionAttributes(new Properties());
|
||||
TransactionAttributeSourceAdvisor tas = new TransactionAttributeSourceAdvisor(ti);
|
||||
SerializationTestUtils.serializeAndDeserialize(tas);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* Format is
|
||||
* <code>FQN.Method=tx attribute representation</code>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 26.04.2003
|
||||
*/
|
||||
public class TransactionAttributeSourceEditorTests extends TestCase {
|
||||
|
||||
public void testNull() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
pe.setAsText(null);
|
||||
TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
|
||||
|
||||
Method m = Object.class.getMethod("hashCode", (Class[]) null);
|
||||
assertTrue(tas.getTransactionAttribute(m, null) == null);
|
||||
}
|
||||
|
||||
public void testInvalid() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
try {
|
||||
pe.setAsText("foo=bar");
|
||||
fail();
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// Ok
|
||||
}
|
||||
}
|
||||
|
||||
public void testMatchesSpecific() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
// TODO need FQN?
|
||||
pe.setAsText(
|
||||
"java.lang.Object.hashCode=PROPAGATION_REQUIRED\n" +
|
||||
"java.lang.Object.equals=PROPAGATION_MANDATORY\n" +
|
||||
"java.lang.Object.*it=PROPAGATION_SUPPORTS\n" +
|
||||
"java.lang.Object.notify=PROPAGATION_SUPPORTS\n" +
|
||||
"java.lang.Object.not*=PROPAGATION_REQUIRED");
|
||||
TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
|
||||
|
||||
checkTransactionProperties(tas, Object.class.getMethod("hashCode", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("equals", new Class[] { Object.class }),
|
||||
TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class }),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class, int.class }),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notify", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notifyAll", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("toString", (Class[]) null), -1);
|
||||
}
|
||||
|
||||
public void testMatchesAll() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
pe.setAsText("java.lang.Object.*=PROPAGATION_REQUIRED");
|
||||
TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
|
||||
|
||||
checkTransactionProperties(tas, Object.class.getMethod("hashCode", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("equals", new Class[] { Object.class }),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class }),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class, int.class }),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notify", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notifyAll", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("toString", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
}
|
||||
|
||||
private void checkTransactionProperties(TransactionAttributeSource tas, Method method, int propagationBehavior) {
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(method, null);
|
||||
if (propagationBehavior >= 0) {
|
||||
assertTrue(ta != null);
|
||||
assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_DEFAULT);
|
||||
assertTrue(ta.getPropagationBehavior() == propagationBehavior);
|
||||
}
|
||||
else {
|
||||
assertTrue(ta == null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* Unit tests for the various {@link TransactionAttributeSource} implementations.
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 15.10.2003
|
||||
* @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
|
||||
*/
|
||||
public final class TransactionAttributeSourceTests {
|
||||
|
||||
@Test
|
||||
public void testMatchAlwaysTransactionAttributeSource() throws Exception {
|
||||
MatchAlwaysTransactionAttributeSource tas = new MatchAlwaysTransactionAttributeSource();
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertTrue(TransactionDefinition.PROPAGATION_REQUIRED == ta.getPropagationBehavior());
|
||||
|
||||
tas.setTransactionAttribute(new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
ta = tas.getTransactionAttribute(
|
||||
IOException.class.getMethod("getMessage", (Class[]) null), IOException.class);
|
||||
assertNotNull(ta);
|
||||
assertTrue(TransactionDefinition.PROPAGATION_SUPPORTS == ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Ignore // no longer works now that setMethodMap has been parameterized
|
||||
@Test
|
||||
public void testMethodMapTransactionAttributeSource() throws NoSuchMethodException {
|
||||
MethodMapTransactionAttributeSource tas = new MethodMapTransactionAttributeSource();
|
||||
Map methodMap = new HashMap();
|
||||
methodMap.put(Object.class.getName() + ".hashCode", TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
methodMap.put(Object.class.getName() + ".toString",
|
||||
new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
tas.setMethodMap(methodMap);
|
||||
tas.afterPropertiesSet();
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Ignore // no longer works now that setMethodMap has been parameterized
|
||||
@Test
|
||||
public void testMethodMapTransactionAttributeSourceWithLazyInit() throws NoSuchMethodException {
|
||||
MethodMapTransactionAttributeSource tas = new MethodMapTransactionAttributeSource();
|
||||
Map methodMap = new HashMap();
|
||||
methodMap.put(Object.class.getName() + ".hashCode", "PROPAGATION_REQUIRED");
|
||||
methodMap.put(Object.class.getName() + ".toString",
|
||||
new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
tas.setMethodMap(methodMap);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Ignore // no longer works now that setMethodMap has been parameterized
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSource() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Map methodMap = new HashMap();
|
||||
methodMap.put("hashCode", "PROPAGATION_REQUIRED");
|
||||
methodMap.put("toString", new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
tas.setNameMap(methodMap);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceWithStarAtStartOfMethodName() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("*ashCode", "PROPAGATION_REQUIRED");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceWithStarAtEndOfMethodName() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("hashCod*", "PROPAGATION_REQUIRED");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceMostSpecificMethodNameIsDefinitelyMatched() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("*", "PROPAGATION_REQUIRED");
|
||||
attributes.put("hashCode", "PROPAGATION_MANDATORY");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_MANDATORY, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceWithEmptyMethodName() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("", "PROPAGATION_MANDATORY");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNull(ta);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* Mock object based tests for TransactionInterceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 16.03.2003
|
||||
*/
|
||||
public class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||
|
||||
protected Object advised(Object target, PlatformTransactionManager ptm, TransactionAttributeSource[] tas) throws Exception {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionManager(ptm);
|
||||
ti.setTransactionAttributeSources(tas);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvice(0, ti);
|
||||
return pf.getProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method to create an advised object given the
|
||||
* target object and transaction setup.
|
||||
* Creates a TransactionInterceptor and applies it.
|
||||
*/
|
||||
protected Object advised(Object target, PlatformTransactionManager ptm, TransactionAttributeSource tas) {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionManager(ptm);
|
||||
assertEquals(ptm, ti.getTransactionManager());
|
||||
ti.setTransactionAttributeSource(tas);
|
||||
assertEquals(tas, ti.getTransactionAttributeSource());
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvice(0, ti);
|
||||
return pf.getProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* A TransactionInterceptor should be serializable if its
|
||||
* PlatformTransactionManager is.
|
||||
*/
|
||||
public void testSerializableWithAttributeProperties() throws Exception {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("methodName", "PROPAGATION_REQUIRED");
|
||||
ti.setTransactionAttributes(props);
|
||||
PlatformTransactionManager ptm = new SerializableTransactionManager();
|
||||
ti.setTransactionManager(ptm);
|
||||
ti = (TransactionInterceptor) SerializationTestUtils.serializeAndDeserialize(ti);
|
||||
|
||||
// Check that logger survived deserialization
|
||||
assertNotNull(ti.logger);
|
||||
assertTrue(ti.getTransactionManager() instanceof SerializableTransactionManager);
|
||||
assertNotNull(ti.getTransactionAttributeSource());
|
||||
}
|
||||
|
||||
public void testSerializableWithCompositeSource() throws Exception {
|
||||
NameMatchTransactionAttributeSource tas1 = new NameMatchTransactionAttributeSource();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("methodName", "PROPAGATION_REQUIRED");
|
||||
tas1.setProperties(props);
|
||||
|
||||
NameMatchTransactionAttributeSource tas2 = new NameMatchTransactionAttributeSource();
|
||||
props = new Properties();
|
||||
props.setProperty("otherMethodName", "PROPAGATION_REQUIRES_NEW");
|
||||
tas2.setProperties(props);
|
||||
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionAttributeSources(new TransactionAttributeSource[] {tas1, tas2});
|
||||
PlatformTransactionManager ptm = new SerializableTransactionManager();
|
||||
ti.setTransactionManager(ptm);
|
||||
ti = (TransactionInterceptor) SerializationTestUtils.serializeAndDeserialize(ti);
|
||||
|
||||
assertTrue(ti.getTransactionManager() instanceof SerializableTransactionManager);
|
||||
assertTrue(ti.getTransactionAttributeSource() instanceof CompositeTransactionAttributeSource);
|
||||
CompositeTransactionAttributeSource ctas = (CompositeTransactionAttributeSource) ti.getTransactionAttributeSource();
|
||||
assertTrue(ctas.getTransactionAttributeSources()[0] instanceof NameMatchTransactionAttributeSource);
|
||||
assertTrue(ctas.getTransactionAttributeSources()[1] instanceof NameMatchTransactionAttributeSource);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We won't use this: we just want to know it's serializable.
|
||||
*/
|
||||
public static class SerializableTransactionManager implements PlatformTransactionManager, Serializable {
|
||||
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void commit(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void rollback(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- Simple target -->
|
||||
<bean id="target" class="org.springframework.beans.DerivedTestBean">
|
||||
<property name="name"><value>custom</value></property>
|
||||
<property name="age"><value>666</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="mockMan" class="org.springframework.transaction.interceptor.PlatformTransactionManagerFacade"/>
|
||||
|
||||
<!--
|
||||
Invalid: we need a transaction attribute source
|
||||
-->
|
||||
<bean id="noTransactionAttributeSource" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="target"><ref local="target"/></property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="targetDependency" class="org.springframework.beans.TestBean">
|
||||
<property name="name"><value>dependency</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Simple target -->
|
||||
<bean id="target" class="org.springframework.beans.DerivedTestBean" lazy-init="true">
|
||||
<property name="name"><value>custom</value></property>
|
||||
<property name="age"><value>666</value></property>
|
||||
<property name="spouse"><ref local="targetDependency"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
|
||||
|
||||
<bean id="mockMan" class="org.springframework.transaction.interceptor.PlatformTransactionManagerFacade"/>
|
||||
|
||||
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="transactionAttributeSource">
|
||||
<value>
|
||||
org.springframework.beans.ITestBean.s*=PROPAGATION_MANDATORY
|
||||
org.springframework.beans.ITestBean.setAg*=PROPAGATION_REQUIRED
|
||||
org.springframework.beans.ITestBean.set*= PROPAGATION_SUPPORTS , readOnly
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory1" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.springframework.beans.ITestBean</value>
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>txInterceptor</value>
|
||||
<value>target</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="baseProxyFactory" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
|
||||
abstract="true">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="s*">PROPAGATION_MANDATORY</prop>
|
||||
<prop key="setAg*"> PROPAGATION_REQUIRED , readOnly </prop>
|
||||
<prop key="set*">PROPAGATION_SUPPORTS</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory2DynamicProxy" parent="baseProxyFactory">
|
||||
<property name="target"><ref local="target"/></property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
Same as proxyFactory2DynamicProxy but forces the use of CGLIB.
|
||||
-->
|
||||
<bean id="proxyFactory2Cglib" parent="baseProxyFactory">
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
<property name="target"><ref local="target"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory2Lazy" parent="baseProxyFactory">
|
||||
<property name="target">
|
||||
<bean class="org.springframework.aop.target.LazyInitTargetSource">
|
||||
<property name="targetBeanName"><idref local="target"/></property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory3" parent="baseProxyFactory">
|
||||
<property name="target"><ref local="target"/></property>
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
<property name="pointcut">
|
||||
<ref local="txnInvocationCounterPointcut"/>
|
||||
</property>
|
||||
<property name="preInterceptors">
|
||||
<list>
|
||||
<ref local="preInvocationCounterInterceptor"/>
|
||||
</list>
|
||||
</property>
|
||||
<property name="postInterceptors">
|
||||
<list>
|
||||
<ref local="postInvocationCounterInterceptor"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean name="cglibNoInterfaces" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="target">
|
||||
<bean class="org.springframework.transaction.interceptor.ImplementsNoInterfaces">
|
||||
<property name="dependency"><ref local="targetDependency"/></property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="*">PROPAGATION_REQUIRED</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
The HotSwappableTargetSource is a Type 3 component.
|
||||
-->
|
||||
<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
|
||||
<constructor-arg><ref local="target"/></constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="hotSwapped" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<!-- Should automatically pick up the target source, rather than simple target -->
|
||||
<property name="target"><ref local="swapper"/></property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="s*">PROPAGATION_MANDATORY</prop>
|
||||
<prop key="setAg*">PROPAGATION_REQUIRED</prop>
|
||||
<prop key="set*">PROPAGATION_SUPPORTS</prop>
|
||||
</props>
|
||||
</property>
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
<property name="optimize"><value>false</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="txnInvocationCounterPointcut"
|
||||
class="org.springframework.transaction.interceptor.BeanFactoryTransactionTests$InvocationCounterPointcut"/>
|
||||
|
||||
<bean id="preInvocationCounterInterceptor" class="org.springframework.transaction.interceptor.BeanFactoryTransactionTests$InvocationCounterInterceptor"/>
|
||||
|
||||
<bean id="postInvocationCounterInterceptor" class="org.springframework.transaction.interceptor.BeanFactoryTransactionTests$InvocationCounterInterceptor"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.transaction.Synchronization;
|
||||
|
||||
import com.ibm.wsspi.uow.UOWAction;
|
||||
import com.ibm.wsspi.uow.UOWActionException;
|
||||
import com.ibm.wsspi.uow.UOWException;
|
||||
import com.ibm.wsspi.uow.UOWManager;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class MockUOWManager implements UOWManager {
|
||||
|
||||
private int type = UOW_TYPE_GLOBAL_TRANSACTION;
|
||||
|
||||
private boolean joined;
|
||||
|
||||
private int timeout;
|
||||
|
||||
private boolean rollbackOnly;
|
||||
|
||||
private int status = UOW_STATUS_NONE;
|
||||
|
||||
private final Map resources = new HashMap();
|
||||
|
||||
private final List synchronizations = new LinkedList();
|
||||
|
||||
|
||||
public void runUnderUOW(int type, boolean join, UOWAction action) throws UOWActionException, UOWException {
|
||||
this.type = type;
|
||||
this.joined = join;
|
||||
try {
|
||||
this.status = UOW_STATUS_ACTIVE;
|
||||
action.run();
|
||||
this.status = (this.rollbackOnly ? UOW_STATUS_ROLLEDBACK : UOW_STATUS_COMMITTED);
|
||||
}
|
||||
catch (Error err) {
|
||||
this.status = UOW_STATUS_ROLLEDBACK;
|
||||
throw err;
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
this.status = UOW_STATUS_ROLLEDBACK;
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.status = UOW_STATUS_ROLLEDBACK;
|
||||
throw new UOWActionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public int getUOWType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public boolean getJoined() {
|
||||
return this.joined;
|
||||
}
|
||||
|
||||
public long getLocalUOWId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setUOWTimeout(int uowType, int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public int getUOWTimeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
this.rollbackOnly = true;
|
||||
}
|
||||
|
||||
public boolean getRollbackOnly() {
|
||||
return this.rollbackOnly;
|
||||
}
|
||||
|
||||
public void setUOWStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getUOWStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public void putResource(Object key, Object value) {
|
||||
this.resources.put(key, value);
|
||||
}
|
||||
|
||||
public Object getResource(Object key) throws NullPointerException {
|
||||
return this.resources.get(key);
|
||||
}
|
||||
|
||||
public void registerInterposedSynchronization(Synchronization sync) {
|
||||
this.synchronizations.add(sync);
|
||||
}
|
||||
|
||||
public List getSynchronizations() {
|
||||
return this.synchronizations;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,629 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.jta;
|
||||
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import com.ibm.wsspi.uow.UOWAction;
|
||||
import com.ibm.wsspi.uow.UOWException;
|
||||
import com.ibm.wsspi.uow.UOWManager;
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.mock.jndi.ExpectedLookupTemplate;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.NestedTransactionNotSupportedException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class WebSphereUowTransactionManagerTests extends TestCase {
|
||||
|
||||
public void testUowManagerFoundInJndi() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
ExpectedLookupTemplate jndiTemplate =
|
||||
new ExpectedLookupTemplate(WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testUowManagerAndUserTransactionFoundInJndi() throws Exception {
|
||||
MockControl utControl = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut = (UserTransaction) utControl.getMock();
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
ut.getStatus();
|
||||
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
ut.begin();
|
||||
utControl.setVoidCallable(1);
|
||||
ut.commit();
|
||||
utControl.setVoidCallable(1);
|
||||
utControl.replay();
|
||||
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
|
||||
jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_USER_TRANSACTION_NAME, ut);
|
||||
jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
TransactionStatus ts = ptm.getTransaction(definition);
|
||||
ptm.commit(ts);
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testPropagationMandatoryFailsInCaseOfNoExistingTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown IllegalTransactionStateException");
|
||||
}
|
||||
catch (IllegalTransactionStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationSupports() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNotSupported() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationSupportsAndSynchOnActual() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNotSupportedAndSynchOnActual() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNeverAndSynchOnActual() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationSupportsAndSynchNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNotSupportedAndSynchNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNeverAndSynchNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
private void doTestNewTransactionSynchronization(int propagationBehavior, final int synchMode) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
ptm.setTransactionSynchronization(synchMode);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(propagationBehavior);
|
||||
definition.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
if (synchMode == WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
else {
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequired() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiresNew() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationNested() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiredAndSynchOnActual() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiresNewAndSynchOnActual() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationNestedAndSynchOnActual() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiredAndSynchNever() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiresNewAndSynchNever() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationNestedAndSynchNever() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
private void doTestNewTransactionWithCommit(int propagationBehavior, final int synchMode) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
ptm.setTransactionSynchronization(synchMode);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(propagationBehavior);
|
||||
definition.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
if (synchMode != WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
else {
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitAndTimeout() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setTimeout(10);
|
||||
definition.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(10, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitException() {
|
||||
final RollbackException rex = new RollbackException();
|
||||
MockUOWManager manager = new MockUOWManager() {
|
||||
public void runUnderUOW(int type, boolean join, UOWAction action) throws UOWException {
|
||||
throw new UOWException(rex);
|
||||
}
|
||||
};
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown TransactionSystemException");
|
||||
}
|
||||
catch (TransactionSystemException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getCause() instanceof UOWException);
|
||||
assertSame(rex, ex.getRootCause());
|
||||
assertSame(rex, ex.getMostSpecificCause());
|
||||
}
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithRollback() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
throw new OptimisticLockingFailureException("");
|
||||
}
|
||||
});
|
||||
fail("Should have thrown OptimisticLockingFailureException");
|
||||
}
|
||||
catch (OptimisticLockingFailureException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertTrue(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithRollbackOnly() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
status.setRollbackOnly();
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertTrue(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testExistingNonSpringTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertTrue(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testPropagationNeverFailsInCaseOfExistingTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown IllegalTransactionStateException");
|
||||
}
|
||||
catch (IllegalTransactionStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testPropagationNestedFailsInCaseOfExistingTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown NestedTransactionNotSupportedException");
|
||||
}
|
||||
catch (NestedTransactionNotSupportedException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithParticipationUsingPropagationRequired() {
|
||||
doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithParticipationUsingPropagationSupports() {
|
||||
doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithParticipationUsingPropagationMandatory() {
|
||||
doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
}
|
||||
|
||||
private void doTestExistingTransactionWithParticipation(int propagationBehavior) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
|
||||
definition2.setPropagationBehavior(propagationBehavior);
|
||||
definition2.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result2";
|
||||
}
|
||||
}));
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertTrue(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithSuspensionUsingPropagationRequiresNew() {
|
||||
doTestExistingTransactionWithSuspension(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithSuspensionUsingPropagationNotSupported() {
|
||||
doTestExistingTransactionWithSuspension(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
private void doTestExistingTransactionWithSuspension(final int propagationBehavior) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
|
||||
definition2.setPropagationBehavior(propagationBehavior);
|
||||
definition2.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertEquals(propagationBehavior == TransactionDefinition.PROPAGATION_REQUIRES_NEW,
|
||||
TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result2";
|
||||
}
|
||||
}));
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
if (propagationBehavior == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
}
|
||||
else {
|
||||
assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
|
||||
}
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testExistingTransactionUsingPropagationNotSupported() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
|
||||
definition2.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
|
||||
definition2.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result2";
|
||||
}
|
||||
}));
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.transaction.support;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class JtaTransactionManagerSerializationTests extends TestCase {
|
||||
|
||||
public void testSerializable() throws Exception {
|
||||
UserTransaction ut1 = createMock(UserTransaction.class);
|
||||
UserTransaction ut2 = createMock(UserTransaction.class);
|
||||
TransactionManager tm = createMock(TransactionManager.class);
|
||||
|
||||
JtaTransactionManager jtam = new JtaTransactionManager();
|
||||
jtam.setUserTransaction(ut1);
|
||||
jtam.setTransactionManager(tm);
|
||||
jtam.setRollbackOnCommitFailure(true);
|
||||
jtam.afterPropertiesSet();
|
||||
|
||||
SimpleNamingContextBuilder jndiEnv = SimpleNamingContextBuilder
|
||||
.emptyActivatedContextBuilder();
|
||||
jndiEnv.bind(JtaTransactionManager.DEFAULT_USER_TRANSACTION_NAME, ut2);
|
||||
JtaTransactionManager serializedJtatm = (JtaTransactionManager) SerializationTestUtils
|
||||
.serializeAndDeserialize(jtam);
|
||||
|
||||
// should do client-side lookup
|
||||
assertNotNull("Logger must survive serialization",
|
||||
serializedJtatm.logger);
|
||||
assertTrue("UserTransaction looked up on client", serializedJtatm
|
||||
.getUserTransaction() == ut2);
|
||||
assertNull("TransactionManager didn't survive", serializedJtatm
|
||||
.getTransactionManager());
|
||||
assertEquals(true, serializedJtatm.isRollbackOnCommitFailure());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor pointcut="execution(* *..ITestBean.*(..))" advice-ref="txAdvice"/>
|
||||
</aop:config>
|
||||
|
||||
<tx:advice id="txAdvice">
|
||||
<tx:attributes>
|
||||
<tx:method name="get*" read-only="true"/>
|
||||
<tx:method name="set*"/>
|
||||
<tx:method name="exceptional"/>
|
||||
</tx:attributes>
|
||||
</tx:advice>
|
||||
|
||||
<tx:advice id="txRollbackAdvice">
|
||||
<tx:attributes>
|
||||
<tx:method name="get*" rollback-for="java.lang.Exception"/>
|
||||
<tx:method name="set*" no-rollback-for="java.lang.RuntimeException"/>
|
||||
</tx:attributes>
|
||||
</tx:advice>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.transaction.CallCountingTransactionManager"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.TestBean"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* The Spring Framework is published under the terms
|
||||
* of the Apache Software License.
|
||||
*/
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Utilities for testing serializability of objects.
|
||||
* Exposes static methods for use in other test cases.
|
||||
* Extends TestCase only to test itself.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class SerializationTestUtils extends TestCase {
|
||||
|
||||
public static void testSerialization(Object o) throws IOException {
|
||||
OutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(o);
|
||||
}
|
||||
|
||||
public static boolean isSerializable(Object o) throws IOException {
|
||||
try {
|
||||
testSerialization(o);
|
||||
return true;
|
||||
}
|
||||
catch (NotSerializableException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(o);
|
||||
oos.flush();
|
||||
baos.flush();
|
||||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
Object o2 = ois.readObject();
|
||||
|
||||
return o2;
|
||||
}
|
||||
|
||||
public SerializationTestUtils(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public void testWithNonSerializableObject() throws IOException {
|
||||
TestBean o = new TestBean();
|
||||
assertFalse(o instanceof Serializable);
|
||||
|
||||
assertFalse(isSerializable(o));
|
||||
|
||||
try {
|
||||
testSerialization(o);
|
||||
fail();
|
||||
}
|
||||
catch (NotSerializableException ex) {
|
||||
// Ok
|
||||
}
|
||||
}
|
||||
|
||||
public void testWithSerializableObject() throws Exception {
|
||||
int x = 5;
|
||||
int y = 10;
|
||||
Point p = new Point(x, y);
|
||||
assertTrue(p instanceof Serializable);
|
||||
|
||||
testSerialization(p);
|
||||
|
||||
assertTrue(isSerializable(p));
|
||||
|
||||
Point p2 = (Point) serializeAndDeserialize(p);
|
||||
assertNotSame(p, p2);
|
||||
assertEquals(x, (int) p2.getX());
|
||||
assertEquals(y, (int) p2.getY());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user