Compare commits

..
Author SHA1 Message Date
Rob Bygrave 3f9c3c1db5 [maven-release-plugin] prepare release avaje-ebeanorm-3.2.3 2013-08-02 12:18:36 +12:00
Rob Bygrave b4df899314 Move agent dependency to 3.2.2 (Fix for Issue 44 @Transactional
handling)
2013-08-02 12:16:41 +12:00
Rob Bygrave 9c7f62e8b1 Allow more flexibility with JSON marshalling of non-entity beans 2013-08-02 12:16:00 +12:00
Rob Bygrave bf8574833a Remove Thread UncaughtExceptionHandler as part of fix for pull/44
@Transactional not rolling back for uncaught RuntimeException - This
change is not required for 44 but is nice cleanup as
UncaughtExceptionHandler is no used.
2013-08-02 12:14:17 +12:00
Rob Bygrave 6f1bb5a9d7 Merge pull request #44 from hei1233212000/master
added a test case to show the issue that the user record does NOT rolback when there is an exception thrown
2013-08-01 16:45:15 -07:00
harry.chan 2f7b4e3a24 added a test case to show the issue that the user record does NOT
rolback when there is an exception thrown
2013-08-01 11:42:38 +08:00
Rob Bygrave 44d95dc06c Fix for Issue 43 - Support for JSON unmarshalling of @XmlRootElement
beans.
2013-07-29 23:24:30 +12:00
Robin Bygrave 6f579ba890 [maven-release-plugin] prepare for next development iteration 2013-07-12 21:10:49 +12:00
8 changed files with 152 additions and 40 deletions
+3 -3
View File
@@ -9,7 +9,7 @@
<groupId>org.avaje.ebeanorm</groupId>
<artifactId>avaje-ebeanorm</artifactId>
<version>3.2.2</version>
<version>3.2.3</version>
<packaging>jar</packaging>
<name>avaje-ebeanorm</name>
@@ -94,7 +94,7 @@
<dependency>
<groupId>org.avaje.ebeanorm</groupId>
<artifactId>avaje-ebeanorm-agent</artifactId>
<version>3.2.1</version>
<version>3.2.2</version>
<scope>test</scope>
</dependency>
@@ -156,7 +156,7 @@
<plugin>
<groupId>org.avaje.ebeanorm</groupId>
<artifactId>avaje-ebeanorm-mavenenhancer</artifactId>
<version>3.2.1</version>
<version>3.2.2</version>
<executions>
<execution>
<id>main</id>
@@ -1,6 +1,5 @@
package com.avaje.ebeaninternal.api;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import com.avaje.ebean.TxScope;
@@ -45,9 +44,6 @@ public class ScopeTrans implements Thread.UncaughtExceptionHandler {
*/
private final ArrayList<Class<? extends Throwable>> rollbackFor;
private final UncaughtExceptionHandler originalUncaughtHandler;
/**
* Flag set when a rollback has occurred.
*/
@@ -65,11 +61,6 @@ public class ScopeTrans implements Thread.UncaughtExceptionHandler {
this.noRollbackFor = txScope.getNoRollbackFor();
this.rollbackFor = txScope.getRollbackFor();
Thread t = Thread.currentThread();
originalUncaughtHandler = t.getUncaughtExceptionHandler();
t.setUncaughtExceptionHandler(this);
}
/**
@@ -81,13 +72,8 @@ public class ScopeTrans implements Thread.UncaughtExceptionHandler {
// rollback transaction if required
caughtThrowable(e);
// reinstate suspended transaction and
// original uncaughtExceptionHandler if required
// reinstate suspended transaction
onFinally();
if (originalUncaughtHandler != null){
originalUncaughtHandler.uncaughtException(thread, e);
}
}
/**
@@ -110,11 +96,7 @@ public class ScopeTrans implements Thread.UncaughtExceptionHandler {
* Also reinstate the suspended transaction if there was one.
*/
public void onFinally() {
try {
if (originalUncaughtHandler != null){
Thread.currentThread().setUncaughtExceptionHandler(originalUncaughtHandler);
}
try {
if (!rolledBack && created) {
transaction.commit();
}
@@ -71,6 +71,7 @@ import com.avaje.ebeaninternal.server.type.TypeManager;
import com.avaje.ebeaninternal.util.SortByClause;
import com.avaje.ebeaninternal.util.SortByClause.Property;
import com.avaje.ebeaninternal.util.SortByClauseParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1318,10 +1319,8 @@ public class BeanDescriptor<T> {
public EntityBean createEntityBean() {
try {
// Note factoryType is used indirectly via beanReflect
EntityBean eb = (EntityBean) beanReflect.createEntityBean();
return eb;
return (EntityBean) beanReflect.createEntityBean();
} catch (Exception ex) {
throw new PersistenceException(ex);
}
@@ -2308,6 +2307,9 @@ public class BeanDescriptor<T> {
for (int j = 0; j < propertiesNonTransient.length; j++) {
propertiesNonTransient[j].jsonWrite(ctx, bean);
}
for (int j = 0; j < propertiesTransient.length; j++) {
propertiesTransient[j].jsonWrite(ctx, bean);
}
}
}
@@ -2372,9 +2374,20 @@ public class BeanDescriptor<T> {
}
@SuppressWarnings("unchecked")
private T createJsonBean() {
if (EntityType.XMLELEMENT.equals(entityType)) {
try {
return beanType.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return (T)createEntityBean();
}
private ReadBeanState jsonReadObject(ReadJsonContext ctx, String path) {
T bean = (T) createEntityBean();
T bean = createJsonBean();
ctx.pushBean(bean, path, this);
do {
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -752,7 +753,11 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
Object value = getValueIntercept(bean);
if (value != null){
ctx.pushParentBeanMany(bean);
help.jsonWrite(ctx, name, value, include != null);
if (help != null){
help.jsonWrite(ctx, name, value, include != null);
} else {
ctx.toJson(name, (Collection<?>)value);
}
ctx.popParentBeanMany();
}
}
@@ -259,10 +259,14 @@ public class DeployCreateProperties {
@SuppressWarnings({ "unchecked", "rawtypes" })
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
try {
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
if (scalarType != null) {
return new DeployBeanPropertySimpleCollection(desc, targetType, scalarType, manyType);
}
} catch (NullPointerException e) {
logger.debug("expected non-scalar type"+e.getMessage());
}
//TODO: Handle Collection of CompoundType and Embedded Type
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
}
@@ -372,7 +376,8 @@ public class DeployCreateProperties {
if (typeArgs[0] instanceof Class<?>){
return (Class<?>) typeArgs[0];
}
throw new RuntimeException("Unexpected Parameterised Type? "+typeArgs[0]);
//throw new RuntimeException("Unexpected Parameterised Type? "+typeArgs[0]);
return null;
}
if (typeArgs.length == 2) {
// this is probably a Map
@@ -216,23 +216,21 @@ public class DJsonContext implements JsonContext {
} else {
BeanDescriptor<?> d = getDecriptor(o.getClass());
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback);
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback, server);
d.jsonWrite(ctx, o);
ctx.end();
}
}
private <T> void toJsonFromCollection(Collection<T> c, WriteJsonBuffer buffer, boolean pretty,
JsonWriteOptions options, String requestCallback){
private <T> void toJsonFromCollection(Collection<T> c, WriteJsonBuffer buffer, boolean pretty, JsonWriteOptions options, String requestCallback){
Iterator<T> it = c.iterator();
if (!it.hasNext()){
buffer.append("[]");
return;
return;
}
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback);
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback, server);
Object o = it.next();
BeanDescriptor<?> d = getDecriptor(o.getClass());
@@ -248,15 +246,14 @@ public class DJsonContext implements JsonContext {
ctx.end();
}
private void toJsonFromMap(Map<Object,Object> map, WriteJsonBuffer buffer, boolean pretty,
JsonWriteOptions options, String requestCallback){
private void toJsonFromMap(Map<Object,Object> map, WriteJsonBuffer buffer, boolean pretty, JsonWriteOptions options, String requestCallback){
if (map.isEmpty()){
buffer.append("{}");
return;
}
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback);
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback, server);
Set<Entry<Object,Object>> entrySet = map.entrySet();
Iterator<Entry<Object, Object>> it = entrySet.iterator();
@@ -1,5 +1,7 @@
package com.avaje.ebeaninternal.server.text.json;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -10,6 +12,8 @@ import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebean.text.json.JsonWriteBeanVisitor;
import com.avaje.ebean.text.json.JsonWriteOptions;
import com.avaje.ebean.text.json.JsonWriter;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.type.EscapeJson;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.util.ArrayStack;
@@ -17,6 +21,8 @@ import com.avaje.ebeaninternal.server.util.ArrayStack;
public class WriteJsonContext implements JsonWriter {
private final SpiEbeanServer server;
private final WriteJsonBuffer buffer;
private final boolean pretty;
@@ -40,8 +46,9 @@ public class WriteJsonContext implements JsonWriter {
boolean assocOne;
public WriteJsonContext(WriteJsonBuffer buffer, boolean pretty, JsonValueAdapter dfltValueAdapter,
JsonWriteOptions options, String requestCallback){
JsonWriteOptions options, String requestCallback, SpiEbeanServer server){
this.server = server;
this.buffer = buffer;
this.pretty = pretty;
this.pathStack = new PathStack();
@@ -61,6 +68,37 @@ public class WriteJsonContext implements JsonWriter {
buffer.append(requestCallback).append("(");
}
}
public void toJson(String name, Collection<?> c) {
beginAssocMany(name);
Iterator<?> it = c.iterator();
if (!it.hasNext()){
endAssocMany();
return;
}
Object o = it.next();
BeanDescriptor<?> d = getDecriptor(o.getClass());
d.jsonWrite(this, o);
while (it.hasNext()) {
appendComma();
Object t = it.next();
d.jsonWrite(this, t);
}
endAssocMany();
}
private <T> BeanDescriptor<T> getDecriptor(Class<T> cls) {
BeanDescriptor<T> d = server.getBeanDescriptor(cls);
if (d == null){
String msg = "No BeanDescriptor found for "+cls;
throw new RuntimeException(msg);
}
return d;
}
public void appendRawValue(String key, String rawJsonValue) {
appendKeyWithComma(key, true);
@@ -0,0 +1,72 @@
package com.avaje.tests.transaction;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.PersistenceException;
import org.avaje.agentloader.AgentLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.annotation.Transactional;
/**
* It shows the issue that the user record does NOT rolback when there is an exception thrown
*/
public class TransactionNotTerminatedAfterRollback {
private static final Logger LOG = LoggerFactory.getLogger(TransactionNotTerminatedAfterRollback.class);
@BeforeClass public static void preStart() {
LOG.debug("... preStart");
// display the log message to see if the UserService is enhanced
AgentLoader.loadAgentFromClasspath("avaje-ebeanorm-agent", "debug=1");
}
@Test public void test() {
try {
new UserService().create(new User(1L, "David"));
fail("Exception should be thrown");
} catch (PersistenceException pe) {
LOG.error("e: " + pe);
}
List<User> users = Ebean.find(User.class).findList();
LOG.debug("users: {}", users);
assertTrue("users should be empty", users.isEmpty());
}
@Transactional(rollbackFor = PersistenceException.class) public class UserService {
public void create(User i) {
Ebean.save(i);
Ebean.save(new User(1L, "Peter")); // make it throw exception and rollback
}
}
@Entity public class User {
@Id Long id;
String name;
public User() {}
public User(Long id, String name) {
this.id = id;
this.name = name;
}
@Override public String toString() {
StringBuilder s = new StringBuilder();
s.append("{");
s.append("id: ").append(id).append(", ");
s.append("name: ").append(name);
s.append("}");
return s.toString();
}
}
}