4646import com .marklogic .client .DatabaseClient ;
4747import com .marklogic .client .DatabaseClientFactory ;
4848import com .marklogic .client .DatabaseClientFactory .Authentication ;
49+ import com .marklogic .client .FailedRequestException ;
50+ import com .marklogic .client .ForbiddenUserException ;
4951import com .marklogic .client .Transaction ;
5052import com .marklogic .client .document .DocumentPage ;
5153import com .marklogic .client .document .DocumentRecord ;
@@ -89,6 +91,107 @@ public class TestSparqlQueryManager extends BasicJavaClientREST {
8991 private static String datasource ;
9092 private static String mbSearchStr = "凌" ;
9193
94+ /*
95+ * Used in testExecuteAskInTransactions method to test transactions
96+ * This returns false.
97+ */
98+ static class ExecuteAskSecondThreadFalse extends Thread {
99+ private boolean bCompleted = false ;
100+ public boolean isbCompleted () {
101+ return bCompleted ;
102+ }
103+ public void setbCompleted (boolean bCompleted ) {
104+ this .bCompleted = bCompleted ;
105+ }
106+ @ Override
107+ public void run () {
108+ Transaction t2 = writeclient .openTransaction ();
109+ try {
110+ System .out .println ("In ExecuteAskSecondThreadFalse run method" );
111+
112+ SPARQLQueryManager sparqlQmgrTh = writeclient .newSPARQLQueryManager ();
113+ StringBuffer sparqlQueryTh = new StringBuffer ();
114+ sparqlQueryTh .append ("ASK FROM <rdfxml> where { <http://example.org/kennedy/person1> <http://purl.org/dc/elements/1.1/title> \" Person\' s title\" @en }" );
115+
116+ SPARQLQueryDefinition qdefTh = sparqlQmgrTh .newQueryDefinition (sparqlQueryTh .toString ());
117+
118+ // Verify result in t2 transaction.
119+ boolean bAskInTransT2 = sparqlQmgrTh .executeAsk (qdefTh , t2 );
120+ System .out .println ("Method ExecuteAskSecondThreadFalse Run result is " + bAskInTransT2 );
121+ assertFalse ("Class ExecuteAskSecondThreadFalse Run result is incorrect. No Records should be returned." , bAskInTransT2 );
122+ setbCompleted (true );
123+
124+ } catch (ForbiddenUserException e ) {
125+ // TODO Auto-generated catch block
126+ e .printStackTrace ();
127+ } catch (FailedRequestException e ) {
128+ // TODO Auto-generated catch block
129+ e .printStackTrace ();
130+ }
131+ finally {
132+ if (t2 != null ) {
133+ t2 .rollback ();
134+ t2 = null ;
135+ }
136+ }
137+ }
138+ }
139+
140+ /*
141+ * Used in testExecuteAskInTransactions method to test transactions
142+ * Sleeps for 5 seconds, so that main thread commits the record
143+ * This returns true.
144+ */
145+ static class ExecuteAskSecondThreadTrue extends Thread {
146+ private boolean bCompleted = false ;
147+
148+ public boolean isbCompleted () {
149+ return bCompleted ;
150+ }
151+
152+ public void setbCompleted (boolean bCompleted ) {
153+ this .bCompleted = bCompleted ;
154+ }
155+
156+ @ Override
157+ public void run () {
158+ Transaction t2 = writeclient .openTransaction ("WaitingTransaction" );
159+ try {
160+ System .out .println ("In ExecuteAskSecondThreadTrue run method" );
161+
162+ SPARQLQueryManager sparqlQmgrTh = writeclient .newSPARQLQueryManager ();
163+ StringBuffer sparqlQueryTh = new StringBuffer ();
164+ sparqlQueryTh .append ("ASK FROM <rdfxml> where { <http://example.org/kennedy/person1> <http://purl.org/dc/elements/1.1/title> \" Person\' s title\" @en }" );
165+
166+ SPARQLQueryDefinition qdefTh = sparqlQmgrTh .newQueryDefinition (sparqlQueryTh .toString ());
167+
168+ // Verify result in t2 transaction.
169+ try {
170+ //sleep for 5 seconds for main thread to finish commit.
171+ Thread .sleep (5000 );
172+ } catch (InterruptedException e ) {
173+ e .printStackTrace ();
174+ }
175+ // By this time the other transaction should (could have?) have commited.
176+ boolean bAskInTransT2 = sparqlQmgrTh .executeAsk (qdefTh , t2 );
177+ System .out .println ("Method ExecuteAskSecondThreadTrue Run result is " + bAskInTransT2 );
178+ assertTrue ("Class ExecuteAskSecondThreadTrue Run result is incorrect. Records should be returned." , bAskInTransT2 );
179+ setbCompleted (true );
180+
181+ } catch (ForbiddenUserException e ) {
182+ // TODO Auto-generated catch block
183+ e .printStackTrace ();
184+ } catch (FailedRequestException e ) {
185+ // TODO Auto-generated catch block
186+ e .printStackTrace ();
187+ }
188+ if (t2 != null ) {
189+ t2 .rollback ();
190+ t2 = null ;
191+ }
192+ }
193+ }
194+
92195 @ BeforeClass
93196 public static void setUp () throws Exception
94197 {
@@ -239,16 +342,14 @@ public void testNamedExecuteSelectQuery() throws IOException, SAXException, Pars
239342 jsonNameNode = nameNodesItr .next ();
240343 // Verify result 1's values.
241344 assertEquals ("Element 1 name value incorrect" , "Karen Schouten" , jsonNameNode .path ("name" ).path ("value" ).asText ());
242- assertEquals ("Element 1 type is incorrect" , "literal" , jsonNameNode .path ("name" ).path ("type" ).asText ());
243- assertEquals ("Element 1 datatype is incorrect" , "http://www.w3.org/2001/XMLSchema#string" , jsonNameNode .path ("name" ).path ("datatype" ).asText ());
345+ assertEquals ("Element 1 type is incorrect" , "literal" , jsonNameNode .path ("name" ).path ("type" ).asText ());
244346 }
245347
246348 if (nameNodesItr .hasNext ()) {
247349 // Verify result 2's values.
248350 jsonNameNode = nameNodesItr .next ();
249351 assertEquals ("Element 2 name value incorrect" , "Nick Aster" , jsonNameNode .path ("name" ).path ("value" ).asText ());
250- assertEquals ("Element 2 type is incorrect" , "literal" , jsonNameNode .path ("name" ).path ("type" ).asText ());
251- assertEquals ("Element 2 datatype is incorrect" , "http://www.w3.org/2001/XMLSchema#string" , jsonNameNode .path ("name" ).path ("datatype" ).asText ());
352+ assertEquals ("Element 2 type is incorrect" , "literal" , jsonNameNode .path ("name" ).path ("type" ).asText ());
252353 }
253354 }
254355
@@ -879,7 +980,7 @@ public void testExecuteAsk() throws IOException, SAXException, ParserConfigurati
879980 System .out .println ("Checking for true value in testExecuteAsk method with empty ASK : " + bAskEmpty );
880981 assertTrue ("Method testExecuteAsk result is incorrect. Expected true for empty ASK query" , bAskEmpty );
881982 }
882-
983+
883984 /* This test checks a simple SPARQL ASK results from named graph in a transaction.
884985 * The database contains triples from rdfxml1.rdf file. The data format in this file is RDFXML.
885986 *
@@ -891,12 +992,12 @@ public void testExecuteAskInTransactions() throws IOException, SAXException, Par
891992 {
892993 System .out .println ("In SPARQL Query Manager Test testExecuteAskInTransactions method" );
893994 Transaction t1 = null ;
894- Transaction t2 = null ;
895995 Transaction tAfterRollback = null ;
896996 Transaction tAnother = null ;
897997 try {
898998
899999 SPARQLQueryManager sparqlQmgr = writeclient .newSPARQLQueryManager ();
1000+ t1 = writeclient .openTransaction ();
9001001 StringBuffer sparqlQuery = new StringBuffer ();
9011002 sparqlQuery .append ("ASK FROM <rdfxml> where { <http://example.org/kennedy/person1> <http://purl.org/dc/elements/1.1/title> \" Person\' s title\" @en }" );
9021003
@@ -909,13 +1010,12 @@ public void testExecuteAskInTransactions() throws IOException, SAXException, Par
9091010
9101011 // RDFXML "application/rdf+xml". Get the content into FileHandle
9111012 File file = new File (datasource + "rdfxml1.rdf" );
912-
9131013 FileHandle filehandle = new FileHandle ();
9141014 filehandle .set (file );
9151015
9161016 // Create Graph manager
9171017 GraphManager sparqlGmgr = writeclient .newGraphManager ();
918- t1 = writeclient . openTransaction ();
1018+
9191019 // Write the triples in the doc into named graph.
9201020 sparqlGmgr .write ("rdfxml" , filehandle .withMimetype (RDFMimeTypes .RDFXML ), t1 );
9211021
@@ -924,17 +1024,13 @@ public void testExecuteAskInTransactions() throws IOException, SAXException, Par
9241024 System .out .println (bAskInTransT1 );
9251025 assertTrue ("Method testExecuteAskInTransactions result is incorrect. Records should be returned." , bAskInTransT1 );
9261026
927- // Verify result in t2 transaction.
928- t2 = writeclient .openTransaction ();
929- boolean bAskInTransT2 = sparqlQmgr .executeAsk (qdef , t2 );
930- System .out .println (bAskInTransT2 );
931- assertFalse ("Method testExecuteAskInTransactions result is incorrect. No Records should be returned." , bAskInTransT2 );
932- // Handle the transactions.
1027+ // Thread1 should be blocked due to ML Server holding a write lock on the record and returns false.
1028+ ExecuteAskSecondThreadFalse thread1 = new ExecuteAskSecondThreadFalse ();
1029+ thread1 .start ();
1030+ // Handle the transactions.
9331031 t1 .rollback ();
934- t2 .rollback ();
935- t1 = null ;
936- t2 = null ;
937-
1032+ t1 = null ;
1033+
9381034 boolean bAskTransRolledback = sparqlQmgr .executeAsk (qdef );
9391035 System .out .println (bAskTransRolledback );
9401036 assertFalse ("Method testExecuteAskInTransactions result is incorrect. No records should be returned." , bAskTransRolledback );
@@ -943,8 +1039,25 @@ public void testExecuteAskInTransactions() throws IOException, SAXException, Par
9431039 tAfterRollback = writeclient .openTransaction ();
9441040 // Write the triples in the doc into either named graph.
9451041 sparqlGmgr .write ("rdfxml" , filehandle .withMimetype (RDFMimeTypes .RDFXML ), tAfterRollback );
1042+
1043+ // Thread2 should be blocked and sleeping, while main thread commits. Thread 2 returns true.
1044+ ExecuteAskSecondThreadTrue thread2 = new ExecuteAskSecondThreadTrue ();
1045+ thread2 .start ();
1046+
9461047 tAfterRollback .commit ();
9471048 tAfterRollback = null ;
1049+ int nCount = 0 ;
1050+ // Now wait for thread2 to complete. To do - Producer/Consumer model helps?.
1051+ while (!thread2 .isbCompleted ()){
1052+ try {
1053+ // Sleep main thread for 1 second and check for 10 times.
1054+ Thread .sleep (1000 );
1055+ } catch (InterruptedException e ) {
1056+ e .printStackTrace ();
1057+ }
1058+ if (nCount ++ > 10 )
1059+ break ;
1060+ }
9481061
9491062 boolean bAskAfterCommit = sparqlQmgr .executeAsk (qdef );
9501063 System .out .println (bAskAfterCommit );
@@ -967,11 +1080,7 @@ public void testExecuteAskInTransactions() throws IOException, SAXException, Par
9671080 if (t1 != null ) {
9681081 t1 .rollback ();
9691082 t1 = null ;
970- }
971- if (t2 != null ) {
972- t2 .rollback ();
973- t2 = null ;
974- }
1083+ }
9751084 if (tAnother != null ) {
9761085 tAnother .rollback ();
9771086 tAnother = null ;
0 commit comments