Neo4J create relationship hangs on remote, but node creation succeeds - java

My relationship creation hangs, yet the nodes underneath manage to persist to my remote client.
public class Baz
{
private static enum CustomRelationships implements RelationshipType {
CATEGORY
}
public void foo()
{
RestGraphDatabse db = new RestGraphDatabase("http://remoteIp:7474/db/data",username,password);
Transaction tx = db.beginTx();
try{
Node a = db.createNode();
a.setProperty("foo", "foo"); // finishes
Node b = db.createNode();
b.setProperty("bar", "bar"); //finishes
a.createRelationshipTo(b, CustomRelationships .CATEGORY); // hangs
System.out.println("Finished relationship");
tx.success();
} finally {
tx.finish();
}
}
}
And I cannot figure out why. There is no stack and the connection doesn't time out.
a.createRelationshipTo(b, DynamicRelationshipType.withName("CATEGORY"));
also hangs
This query executes correctly from the admin shell:
start first=node(19), second=node(20) Create first-[r:RELTYPE {
linkage : first.Baz + '<-->' + second.BazCat }]->second return r
Yet when run in this fashion:
ExecutionResult result = engine.execute("start first=node("
+ entityNode.getId() + "), second=node("
+ categoryNode.getId() + ") "
+ " Create first-[r:RELTYPE { linkage : first.Baz"
+ " + '<-->' + second.BazCat" + " }]->second return r");
Also hangs.

There are no real transactions over rest.
It is a bug in the Java-Rest-Binding that internal threads are not started as daemon threads. It actually doesn't hang just the program is not ended.
You can System.exit(0) to end the program as a workaround.

Related

Non-commited changes not read by transaction with READ_UNCOMMITTED isolation level

I am trying to test how the isolation level of a transaction affects behavior across transactions. When using Isolation.READ_UNCOMMITTED, I was expecting that a different transaction would be able to see any uncommitted changes, however, I cannot see the same.
In the code below, I execute transactionA first. While it initially waits for 10 seconds, I invoke transactionB which inserts a new entity and waits for 15 seconds before committing. By the time transactionB commits, transactionA's wait time is finished. So my expectation is that when I try to fetch the entities from the DB in this method, I should be able to see the uncommitted entity persisted by transactionB. This is not happening (refer to output)
#Transactional(rollbackFor = ApiException.class, isolation = Isolation.READ_UNCOMMITTED)
public void transactionA() throws InterruptedException {
System.out.println("---Txn:A--- " + "START");
wait(10, "---Txn:A--- ");
System.out.println("---Txn:A--- " + "WAIT ENDED");
List<TestEntity> testEntities = testEntityDao.selectAll();
System.out.println("---Txn:A--- " + "FETCHED ALL ENTITIES");
for (TestEntity e : testEntities)
System.out.println("---Txn:A--- " + "ENTITY " + e.getId() + "," + e.getName());
}
#Transactional(rollbackFor = ApiException.class, isolation = Isolation.READ_UNCOMMITTED)
public void transactionB() throws InterruptedException {
System.out.println("---Txn:B--- " + "START");
TestEntity newEntity = new TestEntity();
newEntity.setName("NEW ENTITY TXN_B");
testEntityDao.insert(newEntity);
System.out.println("---Txn:B--- " + "PERSISTED NEW ENTITY");
wait(15, "---Txn:B--- ");
System.out.println("---Txn:B--- " + "WAIT ENDED");
}
Output:
1---Txn:A--- START
2---Txn:B--- START
3---Txn:B--- PERSISTED NEW ENTITY
4---Txn:A--- WAIT ENDED
5---Txn:A--- FETCHED ALL ENTITIES
6---Txn:B--- WAIT ENDED
If any entities were fetched, they should have been printed after line 5 above. However, nothing is being fetched. Why could this be occurring?

Bukkit; How to trigger multiple ClickEvent RUN_COMMAND actions with a single click on a single chat message

I've written a rather simple method for my paper/spigot Minecraft server plugin that detects potential lag machines under construction.
The issue I have is that I want to send a single chat message that, when clicked once, will first run a /vanish command on behalf of the clicker.
Then if (and only if) the vanish was successful, I want to run a teleport command to a location included along with the specific instance of the ClickEvent.
Both of those commands need to be completed from the single user click event.
For reference here is the method that calls notifyOps() and includes the TextComponent in question, msg
if (LagMats.contains(blockType) || mat.contains("MINECART") || mat.contains("DOOR")) {
int counter = 0;
for (Material thisMat: LagMats) {
if (thisMat != Material.GRAVEL) {
counter += Utilities.blockCounter(block.getChunk(), thisMat);
}
}
TextComponent warn = new TextComponent("WARN "); warn.setBold(true);
warn.setColor(ChatColor.RED);
TextComponent msg = new TextComponent("Potential lag-machine at " +
block.getX() + ", " + block.getY() + ", " + block.getZ() + " in " + dimension +
" by " + placer_name + " with UUID: " + placer.getUniqueId());
String cmd = "/execute in " + env + " run tp #s " +
block.getX() + " " + block.getY() + " " + block.getZ();
msg.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, cmd));
if (counter > 256) {
Utilities.notifyOps(new TextComponent(warn, msg));
}
}
Oh and the actual little code of notifyOps where the TextComponent is used in a message:
// send a message to all online ops and console
public static boolean notifyOps(TextComponent msg) {
if (msg == null) return false;
for (Player thisPlayer: Bukkit.getOnlinePlayers()) {
try {
if (thisPlayer.isOp()) thisPlayer.spigot().sendMessage(msg);
} catch (Exception e) {return false;}
}
System.out.println(msg.getText());
return true;
}
So I want to have the user click just once, run two commands, the second only if the first succeeds, and would be best if it could be done within the try block the message is sent from.
I could write a custom command for this purpose, and then just run that command, but I rather avoid adding classes for such a small addition if it's actually possible and I just have no idea.
Thanks for any advice or help!
There is no way of doing that without writing a custom command...
This is impossible because the ClickEvent and HoverEvent are entirely client-side. That means that there are no packets sent from the Player to the server. Therefore, it is impossible to callback the click of the Player and call a method to perform what you are trying to do.
You may notice that all the ClickEvent.Actions do not affect the server. OPEN_URL, OPEN_FILE, RUN_COMMAND, SUGGEST_COMMAND, CHANGE_PAGE and COPY_TO_CLIPBOARD are all actions taken on the client-side.
The only way here is to make the client send a command to the server which will trigger a method.

How to know that rollback has been executed ? [#Transactional]

I have the following case:
I'm iterating over my Affiliate entities and for each of them I need to persist and update data in one unique transaction. So I have a service with a method annotated with Spring #Transactional annotation (where data is created and updated) but I don't know how can I see that the transaction has been rollback for an affiliate ?
I would like to know that for a special Affiliate the transaction has been rollback and retrieve a custom error code from my service..
This was my service before using Spring:
public void savePostingPaymentDetails(List<Posting> postingsToUpdate, List<PaymentPostingDetail> detailsToInsert, Payment payment) {
logger.info("DB ACCESS : INSERT PAYMENT DETAILS & UPDATE POSTINGS");
long begin = System.nanoTime();
this.em.getTransaction().begin();
try {
// TEST
// 1 - Save Payments
this.em.persist(payment);
// 2 - Save Details
for (PaymentPostingDetail ppd : detailsToInsert) {
this.em.persist(ppd);
}
// 3 - Update Postings
for (Posting p : postingsToUpdate) {
if(p.getSignature() != null)
{
p.getSignature().setModification("withholding-tax.pay", new Date());
}
else
{
logger.error("The Posting with id = " + p.getIdentifier() + " has no PersistenceSignature ?!");
}
this.em.merge(p);
}
}
catch (Exception e)
{
logger.error("Unexpected error on saving/updating the DB.", e);
this.em.getTransaction().rollback();
logger.info("RollBack done.");
e.printStackTrace();
System.exit(JobStatus.ABNORMAL_END_OF_EXECUTION_ERROR.getCode());
}
this.em.getTransaction().commit();
logger.info("Details inserted & Postings updated.");
long end = System.nanoTime();
logger.info("Execution time = " + ((end-begin) / 1000000) + " milliseconds.");
logger.info("----------------------------------------------------------");
}
Now I have this:
#Transactional
public void savePostingPaymentDetails(List<Posting> postings, List<PaymentPostingDetail> paymentDetails, Payment payment)
{
logger.info("DB ACCESS : INSERT PAYMENT DETAILS & UPDATE POSTINGS");
long begin = System.nanoTime();
this.paymentRepository.save(payment);
this.ppdRepository.save(paymentDetails);
for(Posting p : postings){
if(p.getSignature() != null)
{
p.getSignature().setModifiedAt(LocalDate.now());
p.getSignature().setModifiedBy(PayCopyrightWithholdingTaxProcess.SIGNATURE);
}
else{
p.setSignature(new PersistenceSignature(LocalDate.now(), PayCopyrightWithholdingTaxProcess.SIGNATURE));
}
this.postingRepository.save(p);
}
long end = System.nanoTime();
logger.info("Execution time = " + ((end-begin) / 1000000) + " milliseconds.");
logger.info("----------------------------------------------------------");
}
But how can I return let us say a special integer (instead of System.exit()) if the transaction has been rollback ?
There is something called User managed Transaction(UMT) and Container managed Transaction (CMT)
When you are using #Transactional you are actually delegating the transaction management to your Spring container (CMT), which is responsible for e.g opening and closing the transaction for you. It
rolls back automatically when unchecked Exception is thrown like NullPointerException, or RuntimeException ). For checked
exceptions you have to specify when the rollback is supposed to occured #Transactional(rollbackFor=myCheckedException.class).
You can also listen, observe how the transaction is doing with a TransactionalEventListener and react with some AOP listening code like shown here. But You are not ultimately managing the Transaction, Spring is doing for you. The client code can't react with some custom code, when something special happens, because the management of the transaction is delegated to Spring.
Therefore you have to fall back on the User managed Transaction, where you open your transaction, commit it and react in case of a rollback. That is exactly the purpose of UMT: giving total control of your transaction.
from your old code you may get something like:
public int savePostingPaymentDetails(List<Posting> postingsToUpdate, List<PaymentPostingDetail> detailsToInsert, Payment payment) {
int returnCode = 1 // 1 -> "success" , 0 -> "failure"
logger.info("DB ACCESS : INSERT PAYMENT DETAILS & UPDATE POSTINGS");
long begin = System.nanoTime();
long end = 0;
this.em.getTransaction().begin();
try {
// TEST
// 1 - Save Payments
this.em.persist(payment);
// 2 - Save Details
for (PaymentPostingDetail ppd : detailsToInsert) {
this.em.persist(ppd);
}
// 3 - Update Postings
for (Posting p : postingsToUpdate) {
if(p.getSignature() != null)
{
p.getSignature().setModification("withholding-tax.pay", new Date());
}
else
{
logger.error("The Posting with id = " + p.getIdentifier() + " has no PersistenceSignature ?!");
}
this.em.merge(p);
}
this.em.getTransaction().commit();
end = System.nanoTime();
}
catch (Exception e)
{
returnCode = 0;
logger.error("Unexpected error on saving/updating the DB.", e);
this.em.getTransaction().rollback();
logger.info("RollBack done.");
// e.printStackTrace();
System.exit(JobStatus.ABNORMAL_END_OF_EXECUTION_ERROR.getCode());
return returnCode;
}
//this.em.getTransaction().commit();
logger.info("Details inserted & Postings updated.");
//long end = System.nanoTime();
logger.info("Execution time = " + ((end-begin) / 1000000) + " milliseconds.");
logger.info("----------------------------------------------------------");
return returnCode = 1;
}
PS: on a side note, best practice would have you to throw an Exception when your commit fails, instead of special code.
your new method signature could be:
public void savePostingPaymentDetails(List<Posting> postingsToUpdate, List<PaymentPostingDetail> detailsToInsert, Payment payment)
throws MyFailedDbOperationException, OtherException {
}
and Throw the exception on your catch block
catch (Exception e)
{
logger.error("Unexpected error on saving/updating the DB.", e);
this.em.getTransaction().rollback();
logger.info("RollBack done.");
throw MyFailedDbOperationException("my db operation failed");
}
You can use a listener (#TransactionalEventListener) to be informed of a rolled back transaction (the listener can be bound to the different phases of a transaction). See section 16.8 of https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html for more information (requires Spring >= 4.2)

Using a Commonj Work Manager to send Asynchronous HTTP calls

I switched from making sequential HTTP calls to 4 REST services, to making 4 simultaneous calls using a commonj4 work manager task executor. I'm using WebLogic 12c. This new code works on my development environment, but in our test environment under load conditions, and occasionally while not under load, the results map is not populated with all of the results. The logging suggests that each work item did receive back the results though. Could this be a problem with the ConcurrentHashMap? In this example from IBM, they use their own version of Work and there's a getData() method, although it doesn't like that method really exists in their class definition. I had followed a different example that just used the Work class but didn't demonstrate how to get the data out of those threads into the main thread. Should I be using execute() instead of schedule()? The API doesn't appear to be well documented. The stuckthreadtimeout is sufficiently high. component.processInbound() actually contains the code for the HTTP call, but I the problem isn't there because I can switch back to the synchronous version of the class below and not have any issues.
http://publib.boulder.ibm.com/infocenter/wsdoc400/v6r0/index.jsp?topic=/com.ibm.websphere.iseries.doc/info/ae/asyncbns/concepts/casb_workmgr.html
My code:
public class WorkManagerAsyncLinkedComponentRouter implements
MessageDispatcher<Object, Object> {
private List<Component<Object, Object>> components;
protected ConcurrentHashMap<String, Object> workItemsResultsMap;
protected ConcurrentHashMap<String, Exception> componentExceptionsInThreads;
...
//components is populated at this point with one component for each REST call to be made.
public Object route(final Object message) throws RouterException {
...
try {
workItemsResultsMap = new ConcurrentHashMap<String, Object>();
componentExceptionsInThreads = new ConcurrentHashMap<String, Exception>();
final String parentThreadID = Thread.currentThread().getName();
List<WorkItem> producerWorkItems = new ArrayList<WorkItem>();
for (final Component<Object, Object> component : this.components) {
producerWorkItems.add(workManagerTaskExecutor.schedule(new Work() {
public void run() {
//ExecuteThread th = (ExecuteThread) Thread.currentThread();
//th.setName(component.getName());
LOG.info("Child thread " + Thread.currentThread().getName() +" Parent thread: " + parentThreadID + " Executing work item for: " + component.getName());
try {
Object returnObj = component.processInbound(message);
if (returnObj == null)
LOG.info("Object returned to work item is null, not adding to producer components results map, for this producer: "
+ component.getName());
else {
LOG.info("Added producer component thread result for: "
+ component.getName());
workItemsResultsMap.put(component.getName(), returnObj);
}
LOG.info("Finished executing work item for: " + component.getName());
} catch (Exception e) {
componentExceptionsInThreads.put(component.getName(), e);
}
}
...
}));
} // end loop over producer components
// Block until all items are done
workManagerTaskExecutor.waitForAll(producerWorkItems, stuckThreadTimeout);
LOG.info("Finished waiting for all producer component threads.");
if (componentExceptionsInThreads != null
&& componentExceptionsInThreads.size() > 0) {
...
}
List<Object> resultsList = new ArrayList<Object>(workItemsResultsMap.values());
if (resultsList.size() == 0)
throw new RouterException(
"The producer thread results are all empty. The threads were likely not created. In testing this was observed when either 1)the system was almost out of memory (Perhaps the there is not enough memory to create a new thread for each producer, for this REST request), or 2)Timeouts were reached for all producers.");
//** The problem is identified here. The results in the ConcurrentHashMap aren't the number expected .
if (workItemsResultsMap.size() != this.components.size()) {
StringBuilder sb = new StringBuilder();
for (String str : workItemsResultsMap.keySet()) {
sb.append(str + " ");
}
throw new RouterException(
"Did not receive results from all threads within the thread timeout period. Only retrieved:"
+ sb.toString());
}
LOG.info("Returning " + String.valueOf(resultsList.size()) + " results.");
LOG.debug("List of returned feeds: " + String.valueOf(resultsList));
return resultsList;
}
...
}
}
I ended up cloning the DOM document used as a parameter. There must be some downstream code that has side effects on the parameter.

Where is the deadlock in this example?

I am currently reading a section on concurrency in The Well-Grounded Java Developer book and this particular code sample demonstrating block concurrency should deadlock, but as far as I can see it does not. Here's the code:
public class MicroBlogNode implements SimpleMicroBlogNode {
private final String ident;
public MicroBlogNode(String ident_){
ident = ident_;
}
public String getIdent(){
return ident;
}
public static Update getUpdate(String _name){
return new Update(_name);
}
public synchronized void propagateUpdate(Update upd_, MicroBlogNode backup_){
System.out.println(ident + ": received: " + upd_.getUpdateText() + " ; backup: " + backup_.getIdent());
backup_.confirmUpdate(this, upd_);
}
public synchronized void confirmUpdate(MicroBlogNode other_, Update update_){
System.out.println(ident + ": received confirm: " + update_.getUpdateText() + " from " + other_.getIdent() + "\n");
}
public static void main(String[] args) {
final MicroBlogNode local = new MicroBlogNode("localhost");
final MicroBlogNode other = new MicroBlogNode("remotehost");
final Update first = getUpdate("1");
final Update second = getUpdate("2");
new Thread(new Runnable() {
public void run() {
local.propagateUpdate(first, other);
}
}).start();
new Thread(new Runnable() {
public void run() {
other.propagateUpdate(second, local);
}
}).start();
}
}
When I run it I get the following output:
localhost: received: 1 ; backup: remotehost
remotehost: received confirm: 1 from localhost
remotehost: received: 2 ; backup: localhost
localhost: received confirm: 2 from remotehost
The book says that if you run the code, you’ll normally see an example of a deadlock—both threads will report receiving the update, but neither will confirm receiving the update for
which they’re the backup thread. The reason for this is that each thread requires the other to release the lock it holds before the confirmation method can progress.
As far as I can see this is not the case - each thread confirms receiving the update for which they are the backup thread.
Thanks in advance.
This looks like timing. Your output is showing that the localhost thread has completed before the remotehost (other) thread has started.
Try putting a Thread.sleep(1000) in the propogateUpdate method after the System.out
public synchronized void propagateUpdate(Update upd_, MicroBlogNode backup_){
System.out.println(ident + ": received: " + upd_.getUpdateText() + " ; backup: " + backup_.getIdent());
Thread.sleep(1000);
backup_.confirmUpdate(this, upd_);
}
This should force a deadlock.
The deadlock is happening when you have your local calling a threaded operation on confirmUpdate when other is attempting to make the same call. Hence, the deadlock happens following this order of operations
Local locks itself by calling propagateUpdate due to the declaration that it is synchronized (see Synchronized Member Function in Java)
'Other' locks itself by calling propagateUpdate
Local attempts to acquire the lock on Other to call confirmUpdate but can't since Other has already been locked in the other thread.
Other attempts to do the same thing and fails for the same reason.
If it's actually working, it's probably because it's happening so fast. Run it a few more times. Thread issue never work when you want them to work.

Categories

Resources