mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f9c3c1db5 | ||
|
|
b4df899314 | ||
|
|
9c7f62e8b1 | ||
|
|
bf8574833a | ||
|
|
6f1bb5a9d7 | ||
|
|
2f7b4e3a24 | ||
|
|
44d95dc06c | ||
|
|
6f579ba890 |
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user