简体   繁体   中英

How to use camel JPA component on the same database with multiple servers?

I am currently setting up my camel project and I can't make my JPA poller to work on several concurrent servers.

Here is the my camel route :

public class TicketPoller extends RouteBuilder {

    /** The uri. */
    private final String uri = "jpa://Ticket?consumeDelete=false&consumeLockEntity=true&consumer.SkipLockedEntity=true&consumer.query=select t from Ticket t where t.state=1";

    @Override
    public void configure() {
        from(uri).to("log:input");

    }
}

I use @Consumed annotation to change the ticket state when polled directly in my Hibernate entity :

@Entity
@Table(name = "TICKET", schema = "TEIKITEL")
public class Ticket implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "TICKET_ID")
    private String ticketId;

    @Column(name = "STATE")
    private int state;

    ...

    @Consumed
    public void changeTicketState() {
        this.state = 2;
    }

    @Override
    public String toString() {
        return "Ticket@ticketId=" + this.ticketId;
    }
}

It works fine when I launch it on one single Tomcat server (Tomcat 8) from Eclipse.

But when I launch 2 servers polling on the same database I have these errors when I insert some lines in my TICKET table :

On my first server I can see this :

Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,796 INFO  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] input(180) - Exchange[ExchangePattern: InOnly, BodyType: com.teikitel.model.entity.Ticket, Body: Ticket@ticketId=TICKET1]
Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,812 INFO  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] input(180) - Exchange[ExchangePattern: InOnly, BodyType: com.teikitel.model.entity.Ticket, Body: Ticket@ticketId=TICKET2]

On my second server :

Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,859 WARN  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(144) - SQL Error: 54, SQLState: 61000
2016-04-05 15:04:56,859 ERROR [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(146) - ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
Hibernate: select TICKET_ID from TEIKITEL.TICKET where TICKET_ID =? for update nowait
2016-04-05 15:04:56,874 WARN  [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(144) - SQL Error: 54, SQLState: 61000
2016-04-05 15:04:56,874 ERROR [Camel (camel-1) thread #0 - jpa://com.teikitel.model.entity.Ticket] o.h.e.j.spi.SqlExceptionHelper(146) - ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

Did someone run into the same problem ?

Loic

There is no errors !

These error logs come from Hibernate, not from Camel.

Camel does its Job and skip the element locked in database (your log action triggered is executed only once on one instance) but it uses Hibernate to perform its non-blocking select request. Hibernate throw an exception which is successfully ignored by Camel BUT print the error in your log output. This is what you see.

I gess the solution to your problem is to set the Hibernate log to a higher level.

With problems like theses (synchro) do not hesitate to use the delay method in camel to understand better :

public class TicketPoller extends RouteBuilder {

/** The uri. */
private final String uri = "jpa://Ticket?consumeDelete=false&consumeLockEntity=true&consumer.SkipLockedEntity=true&consumer.query=select t from Ticket t where t.state=1";

@Override
public void configure() {
    from(uri).delay(10000).to("log:input"); //wait 10sec 

}

}

it seems like the entity is already locked for the other thread running in the first server. You are locking the cell with consumeLockEntity=true and you are not waiting for the release consumer.SkipLockedEntity=true so the connection in the second server is close after trying without waiting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM