Fix unneccesary database flush operation

This commit is contained in:
James 2016-11-08 22:48:04 -05:00
parent 89e3021588
commit ef9f0bc35b
5 changed files with 154 additions and 106 deletions

View File

@ -1422,8 +1422,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
theEntity = myEntityManager.merge(theEntity);
myEntityManager.flush();
if (theResource != null) {
populateResourceId(theResource, theEntity);
}

View File

@ -57,6 +57,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
private Properties jpaProperties() {
Properties extraProperties = new Properties();
extraProperties.put("hibernate.jdbc.batch_size", "50");
extraProperties.put("hibernate.format_sql", "false");
extraProperties.put("hibernate.show_sql", "false");
extraProperties.put("hibernate.hbm2ddl.auto", "update");

View File

@ -15,6 +15,7 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
@ -52,6 +53,27 @@ public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {
}
private void stopClientAndWaitForStopped(WebSocketClient client) throws Exception {
client.stop();
/*
* When websocket closes, the subscription is automatically deleted. This
* can cause deadlocks if the test returns too quickly since it also
* tries to delete the subscription
*/
ca.uhn.fhir.model.dstu2.resource.Bundle found = null;
for (int i = 0; i < 10; i++) {
found = ourClient.search().forResource("Subscription").returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class).execute();
if (found.getEntry().size() > 0) {
Thread.sleep(200);
} else {
break;
}
}
assertEquals(0, found.getEntry().size());
}
@Before
public void beforeEnableScheduling() {
myDaoConfig.setSchedulingDisabled(false);
@ -251,7 +273,7 @@ public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {
} finally {
try {
client.stop();
stopClientAndWaitForStopped(client);
} catch (Exception e) {
ourLog.error("Failure", e);
fail(e.getMessage());
@ -317,7 +339,7 @@ public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test {
} finally {
try {
client.stop();
stopClientAndWaitForStopped(client);
} catch (Exception e) {
ourLog.error("Failure", e);
fail(e.getMessage());

View File

@ -14,6 +14,7 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Subscription;
@ -35,28 +36,9 @@ import ca.uhn.fhir.util.TestUtil;
public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
private static final String WEBSOCKET_PATH = "/websocket/dstu3";
public class BaseSocket {
protected String myError;
protected boolean myGotBound;
protected int myPingCount;
protected String mySubsId;
}
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SubscriptionsDstu3Test.class);
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
@Before
public void beforeEnableScheduling() {
myDaoConfig.setSchedulingDisabled(false);
}
private static final String WEBSOCKET_PATH = "/websocket/dstu3";
@Override
public void beforeCreateInterceptor() {
@ -67,6 +49,12 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
myDaoConfig.getInterceptors().add(interceptor);
}
@Before
public void beforeEnableScheduling() {
myDaoConfig.setSchedulingDisabled(false);
}
private void sleepUntilPingCount(BaseSocket socket, int wantPingCount) throws InterruptedException {
/*
* In a separate thread, start a polling for new resources. Normally the scheduler would
@ -106,6 +94,27 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
assertEquals(wantPingCount, socket.myPingCount);
}
private void stopClientAndWaitForStopped(WebSocketClient client) throws Exception {
client.stop();
/*
* When websocket closes, the subscription is automatically deleted. This
* can cause deadlocks if the test returns too quickly since it also
* tries to delete the subscription
*/
Bundle found = null;
for (int i = 0; i < 10; i++) {
found = ourClient.search().forResource("Subscription").returnBundle(Bundle.class).execute();
if (found.getEntry().size() > 0) {
Thread.sleep(200);
} else {
break;
}
}
assertEquals(0, found.getEntry().size());
}
@Test
public void testCreateInvalidNoStatus() {
Subscription subs = new Subscription();
@ -130,36 +139,6 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
ourClient.update().resource(subs).execute();
}
@Test
public void testUpdateToInvalidStatus() {
Subscription subs = new Subscription();
subs.getChannel().setType(SubscriptionChannelType.RESTHOOK);
subs.setCriteria("Observation?identifier=123");
subs.setStatus(SubscriptionStatus.REQUESTED);
IIdType id = ourClient.create().resource(subs).execute().getId();
subs.setId(id);
try {
subs.setStatus(SubscriptionStatus.ACTIVE);
ourClient.update().resource(subs).execute();
fail();
} catch (UnprocessableEntityException e) {
assertEquals("HTTP 422 Unprocessable Entity: Subscription.status can not be changed from 'requested' to 'active'", e.getMessage());
}
try {
subs.setStatus((SubscriptionStatus) null);
ourClient.update().resource(subs).execute();
fail();
} catch (UnprocessableEntityException e) {
assertEquals("HTTP 422 Unprocessable Entity: Can not update resource: Subscription.status must be populated", e.getMessage());
}
subs.setStatus(SubscriptionStatus.OFF);
ourClient.update().resource(subs).execute();
}
@Test
public void testCreateInvalidWrongStatus() {
Subscription subs = new Subscription();
@ -237,7 +216,7 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
} finally {
try {
client.stop();
stopClientAndWaitForStopped(client);
} catch (Exception e) {
ourLog.error("Failure", e);
fail(e.getMessage());
@ -246,7 +225,7 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
}
@Test
public void testSubscriptionDynamicXml() throws Exception {
myDaoConfig.setSubscriptionEnabled(true);
@ -303,7 +282,7 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
} finally {
try {
client.stop();
stopClientAndWaitForStopped(client);
} catch (Exception e) {
ourLog.error("Failure", e);
fail(e.getMessage());
@ -311,7 +290,7 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
}
}
@Test
public void testSubscriptionSimple() throws Exception {
myDaoConfig.setSubscriptionEnabled(true);
@ -372,6 +351,7 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
}
@Test
public void testUpdateFails() {
Subscription subs = new Subscription();
@ -401,6 +381,97 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
subs.setStatus(SubscriptionStatus.OFF);
}
@Test
public void testUpdateToInvalidStatus() {
Subscription subs = new Subscription();
subs.getChannel().setType(SubscriptionChannelType.RESTHOOK);
subs.setCriteria("Observation?identifier=123");
subs.setStatus(SubscriptionStatus.REQUESTED);
IIdType id = ourClient.create().resource(subs).execute().getId();
subs.setId(id);
try {
subs.setStatus(SubscriptionStatus.ACTIVE);
ourClient.update().resource(subs).execute();
fail();
} catch (UnprocessableEntityException e) {
assertEquals("HTTP 422 Unprocessable Entity: Subscription.status can not be changed from 'requested' to 'active'", e.getMessage());
}
try {
subs.setStatus((SubscriptionStatus) null);
ourClient.update().resource(subs).execute();
fail();
} catch (UnprocessableEntityException e) {
assertEquals("HTTP 422 Unprocessable Entity: Can not update resource: Subscription.status must be populated", e.getMessage());
}
subs.setStatus(SubscriptionStatus.OFF);
ourClient.update().resource(subs).execute();
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
public class BaseSocket {
protected String myError;
protected boolean myGotBound;
protected int myPingCount;
protected String mySubsId;
}
/**
* Basic Echo Client Socket
*/
@WebSocket(maxTextMessageSize = 64 * 1024)
public class DynamicEchoSocket extends BaseSocket {
private String myCriteria;
private EncodingEnum myEncoding;
private List<IBaseResource> myReceived = new ArrayList<IBaseResource>();
@SuppressWarnings("unused")
private Session session;
public DynamicEchoSocket(String theCriteria, EncodingEnum theEncoding) {
myCriteria = theCriteria;
myEncoding = theEncoding;
}
@OnWebSocketConnect
public void onConnect(Session session) {
ourLog.info("Got connect: {}", session);
this.session = session;
try {
String sending = "bind " + myCriteria;
ourLog.info("Sending: {}", sending);
session.getRemote().sendString(sending);
} catch (Throwable t) {
ourLog.error("Failure", t);
}
}
@OnWebSocketMessage
public void onMessage(String theMsg) {
ourLog.info("Got msg: {}", theMsg);
if (theMsg.startsWith("bound ")) {
myGotBound = true;
mySubsId = (theMsg.substring("bound ".length()));
myPingCount++;
} else if (myGotBound && theMsg.startsWith("add " + mySubsId + "\n")) {
String text = theMsg.substring(("add " + mySubsId + "\n").length());
IBaseResource res = myEncoding.newParser(myFhirCtx).parseResource(text);
myReceived.add(res);
myPingCount++;
} else {
myError = "Unexpected message: " + theMsg;
}
}
}
/**
* Basic Echo Client Socket
*/
@ -439,52 +510,4 @@ public class SubscriptionsDstu3Test extends BaseResourceProviderDstu3Test {
}
}
}
/**
* Basic Echo Client Socket
*/
@WebSocket(maxTextMessageSize = 64 * 1024)
public class DynamicEchoSocket extends BaseSocket {
private List<IBaseResource> myReceived = new ArrayList<IBaseResource>();
@SuppressWarnings("unused")
private Session session;
private String myCriteria;
private EncodingEnum myEncoding;
public DynamicEchoSocket(String theCriteria, EncodingEnum theEncoding) {
myCriteria = theCriteria;
myEncoding = theEncoding;
}
@OnWebSocketConnect
public void onConnect(Session session) {
ourLog.info("Got connect: {}", session);
this.session = session;
try {
String sending = "bind " + myCriteria;
ourLog.info("Sending: {}", sending);
session.getRemote().sendString(sending);
} catch (Throwable t) {
ourLog.error("Failure", t);
}
}
@OnWebSocketMessage
public void onMessage(String theMsg) {
ourLog.info("Got msg: {}", theMsg);
if (theMsg.startsWith("bound ")) {
myGotBound = true;
mySubsId = (theMsg.substring("bound ".length()));
myPingCount++;
} else if (myGotBound && theMsg.startsWith("add " + mySubsId + "\n")) {
String text = theMsg.substring(("add " + mySubsId + "\n").length());
IBaseResource res = myEncoding.newParser(myFhirCtx).parseResource(text);
myReceived.add(res);
myPingCount++;
} else {
myError = "Unexpected message: " + theMsg;
}
}
}
}

View File

@ -256,6 +256,10 @@
Correct several documentation issues. Thanks to Vadim Peretokin
for the pull requests!
</action>
<action type="add">
Remove an unneccesary database flush
from JPA persistence operations
</action>
</release>
<release version="2.0" date="2016-08-30">
<action type="fix">