I'm not an expert on using JPA. The following link suggests that there is a way to configure query timeout in an xml-formatted JPA configuration file: http://www.mastertheboss.com/hibernate-jpa/jpa-configuration/3-ways-to-set-a-query-timeout-for-jpa-hibernate-applications/

On 4/20/22 5:59 AM, Marco Ferretti wrote:
Ok I have an update.

I have tested on PostgreSQL and I do get the timeout.
In order to create a simple case I have created a simple stored procedure on pg 
:

CREATE OR REPLACE PROCEDURE test_timeout("test" integer)
LANGUAGE SQL
AS $$
select count(*) from pg_sleep("test")
$$;

and the call
em.createStoredProcedureQuery("test_timeout")
.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN)
.setParameter(1, 5)
.setHint("javax.persistence.query.timeout", 1)
.execute();

actually throws the exception.
I have then created a simple Derby database (empty) in which I have created my 
procedure
CREATE SCHEMA TEST;
CALL 
SQLJ.INSTALL_JAR('file:///home/marco/devel/stored_procedures/target/storedprocedure-1.0.jar',
 'TEST.test', 0);
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 
'TEST.test');

DROP PROCEDURE APP.test_timeout;
CREATE PROCEDURE TEST.test_timeout (IN WAIT BIGINT)
PARAMETER STYLE JAVA
NO SQL
LANGUAGE JAVA
EXTERNAL NAME 'org.me.storedprocedure.Procedures.db_wait';

Here's the super dummy procedure if you want to try:
public static void db_wait(long wait) throws Exception {
Thread.sleep(wait*1000);
}

Running this code :
public boolean testStoredProcedure(EntityManager em ) throws Exception {
em.createStoredProcedureQuery("test.test_timeout")
.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN)
.setParameter(1, 5)
.setHint("javax.persistence.query.timeout", 1)
.execute();
return false;
}

Against Postgresql :
[EL Warning]: 2022-04-20 14:52:29.152--UnitOfWork(392289808)--Exception 
[EclipseLink-4002] (Eclipse Persistence Services - 2.7.3.v20180807-4be1041): 
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: canceling 
statement due to user request
Where: SQL statement "select count(*) from pg_sleep("test")"
PL/pgSQL function test.test_timeout(integer) line 5 at SQL statement
Error Code: 0
Call: SELECT * FROM test.test_timeout(?)
bind => [1 parameter bound]
Query: ResultSetMappingQuery()
javax.persistence.PersistenceException:Exception [EclipseLink-4002] (Eclipse 
Persistence Services - 2.7.3.v20180807-4be1041): 
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: canceling 
statement due to user request
Where: SQL statement "select count(*) from pg_sleep("test")"
PL/pgSQL function test.test_timeout(integer) line 5 at SQL statement
Error Code: 0
Call: SELECT * FROM test.test_timeout(?)
bind => [1 parameter bound]
Query: ResultSetMappingQuery()
[EL Info]: connection: 2022-04-20 
14:52:29.162--ServerSession(1406848276)--/file:/home/marco/devel/test_jpa/target/classes/_test-pu
 logout successful

Against Derby (Embedded):
[EL Info]: 2022-04-20 14:48:40.742--ServerSession(256346753)--EclipseLink, 
version: Eclipse Persistence Services - 2.7.3.v20180807-4be1041
[EL Info]: connection: 2022-04-20 
14:48:41.028--ServerSession(256346753)--/file:/home/marco/devel/test_jpa/target/classes/_test-pu
 login successful
[EL Info]: connection: 2022-04-20 
14:48:46.144--ServerSession(256346753)--/file:/home/marco/devel/test_jpa/target/classes/_test-pu
 logout successful

As you can see the call is cancelled after 1 millisecond when run against 
postgresql while it is not while run against derby
The two jdbc drivers I used :
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.14.2.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.4</version>
</dependency>

Am I hitting a derby/derby-jdbc limitation or am I missing some configuration ?
Thanks in advance for any help you can provide

On Apr 19 2022, at 11:57 pm, Marco Ferretti <marco.ferre...@gmail.com> wrote:
Hi Brian,
Thanks for your reply and attempt to help.

Here's what I do:
Within the database (preparation of the test)
CALL 
SQLJ.replace_jar('file:///home/marco/devel/stored_procedures/target/storedprocedure-1.0.jar',
 'APP.STORED_PROCS');

CREATE PROCEDURE APP.P_MUI_EXPORT_PIANIFICAZIONE (IN ID_PROMOZIONE BIGINT , IN 
ID_COMPRATORE VARCHAR(255), IN CODICE_UTENTE VARCHAR(50) )
PARAMETER STYLE JAVA
MODIFIES SQL DATA
LANGUAGE JAVA
EXTERNAL NAME 'com.foo.Procedures.exportPianificazione';

Here's the relevant parts of the (dummy) stored procedure:
public static void exportPianificazione(long idPromozione, String idCompratori, 
String codiceUtente)
throws DbPromoException {
try (Connection conn = DriverManager.getConnection("jdbc:default:connection");) 
{
new Utils().dummyExportPianificazione("APP", conn, idPromozione, idCompratori, 
codiceUtente);
} catch (Exception e) {
log.log(Level.SEVERE, "Error writing values in mui_check_testata", e);
throw new DbPromoException("Error writing values in mui_check_testata : " + 
e.getMessage(), e);
}
}

within the Utils class:
public void dummyExportPianificazione(String schema, Connection conn, long 
idPromozione, String idCompratori,
String codiceUtente) throws SQLException, InterruptedException {
String query = "insert into "+schema+".MUI_CHECK_COMPRATORI (ID, ID_PROMOZIONE, 
ID_COMPRATORE, ESITO, CODICE_UTENTE_INSERIMENTO, CODICE_UTENTE_AGGIORNAMENTO, DATA_INSERIMENTO, 
DATA_AGGIORNAMENTO ) values ("
+ "NEXT VALUE FOR MUI_CHECK_COMPRATORI_ID_SEQ, ?, ?, ?, ?, ?, ?, ?)";
String delete = "delete from " + schema
+ ".MUI_CHECK_COMPRATORI where id_promozione = ? and id_compratore = ?";
String esito=getEsito(); //random generation of a result
String[] compratori = idCompratori.split(",");
TimeUnit.SECONDS.wait(10);
....
}



In my application call :
...
milliseconds = 1;

...
getEm().createStoredProcedureQuery(Constants.SP_EXPORT_PIANIFICAZIONE)
.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN)
.registerStoredProcedureParameter(2, String.class, ParameterMode.IN)
.registerStoredProcedureParameter(3, String.class, 
ParameterMode.IN).setParameter(1, myPromo)
.setParameter(2, idCompratori).setParameter(3, username)
.setHint("javax.persistence.query.timeout", milliseconds)
.execute();
....

Activating the JPA logs (EclipseLink) to level FINEST I can see that it takes 
10 seconds between the call to the stored procedure and the the next step of my 
application.
I have also checked that the version of EclipseLink that I am using supports this 
hint and that the default unit of the hint is millisecons (but even if it was 
seconds, it should throw the timeout as 1<10).

What is a real puzzle to me is the fact that I am not getting an exception when I call 
the stored procedure from the application thus my doubt: do I have to 
"activate" something in the jdbc driver/database in order to actually fire the 
timeout ?
The other option is that I did not understand at all how this hint should work 
(which, at this point, would make sense)

Thanks in advance
On Apr 19 2022, at 10:05 pm, Bryan Pendleton <bpendleton.de...@gmail.com> wrote:
I think that Marco is trying to *test* how his code handles a timeout 
exception, but he doesn't know a way to force a timeout exception to occur 
during his test.

I don't know a trivial way to do this, either.

I think you might have to write a more complex test program, for example you 
could have two threads, and two transactions, and in the first thread you could 
begin a transaction and update a record BUT NOT COMMIT.

Then, in the second thread, you could begin a transaction and call your stored 
procedure to run a query against that record, but the query should block 
because the record is updated by the first transaction in the first thread.

Then, after some time expires, you should get the timeout exception in your 
stored procedure.

thanks,

bryan


On Tue, Apr 19, 2022 at 9:30 AM Marco Ferretti <marco.ferre...@gmail.com 
(mailto:marco.ferre...@gmail.com)> wrote:
Hi Rick,

thanks for taking the time to reply.
I am not 100% sure what you mean. My application uses JPA and the Entity 
Manager is getting the connection from the container's datasource: I do not 
have (direct) access to the java.sql.Statement.
What I (would like to) do is calling the a stored procedure in this way:

getEm().createStoredProcedureQuery(Constants.SP_EXPORT_PIANIFICAZIONE)
.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN)
.registerStoredProcedureParameter(2, String.class, ParameterMode.IN)
.registerStoredProcedureParameter(3, String.class, 
ParameterMode.IN).setParameter(1, myPromo)
.setParameter(2, idCompratori).setParameter(3, username)
.setHint("javax.persistence.query.timeout", milliseconds)
.execute();

As far as the JPA API specification (and EclipseLink implementation) goes, the 
".setHint("javax.persistence.query.timeout", milliseconds)" should be 
equivalent to what you suggest.
The problem is that I cannot make the stored procedure call to throw a 
QueryTimeoutException even if my dummy procedure (in derby) waits for 10 
seconds and I set the timeout to 1 millisecond.
I am using, in my test environment, Apache Tomee (java 8) , derby client 10.14 and 
a docker image with a derby network server 
(https://github.com/az82/docker-derby/blob/master/Dockerfile 
(https://link.getmailspring.com/link/3174774e-c496-42ab-83b1-dfe1a95ae...@getmailspring.com/0?redirect=https%3A%2F%2Fgithub.com%2Faz82%2Fdocker-derby%2Fblob%2Fmaster%2FDockerfile&recipient=ZGVyYnktdXNlckBkYi5hcGFjaGUub3Jn))
 .

As far as my knowledge goes, and it's not that far, the reasons I am not 
getting a timeout are :
I am not correctly using the hint

I am not correctly setting up the datasource

There is no timeout because the stored procedure terminates within the given 
timeout.


On point 3: in my (dummy) implementation of the stored procedure i do, before 
doing anything else, a TimeUnit.SECONDS.wait(10);
On point 1 : I am lost. I think I am using the hint correctly (at least the API 
docs say so)
On point 2: I am setting up the datasource with the minimum configuration 
possible :
<Resource id="jdbc/myDatasource" type="DataSource"> JdbcDriver 
org.apache.derby.jdbc.ClientDriver JdbcUrl jdbc:derby://database:1527/dbpromo;create=false UserName DBPROMO 
Password dbpromo </Resource>
Could it be that I am failing to activate something on the Derby side ?

Thanks in advance
Marco

On Apr 19 2022, at 4:57 pm, Rick Hillegas <rick.hille...@gmail.com 
(mailto:rick.hille...@gmail.com)> wrote:
java.sql.Statement.setQueryTimeout(int) should do the trick.

On 4/19/22 3:30 AM, Marco Ferretti wrote:
Hi all,
I am trying to simulate a query timeout in a stored procedure by simply adding 
a delay in my (test) jar.
I then am launching the stored procedure in my java code via JPA and try to set 
a timeout hint by adding
.setHint("javax.persistence.query.timeout", milliseconds)
but I am not able to register a timeout.
I am wondering if there is some derby property or jdbc property I should use to 
activate such behavior. I have tried to google for it but I am having extremely 
bad results... but according to this 
(https://docs.oracle.com/cd/E25178_01/apirefs.1111/e13952/pagehelp/J2EEkodojdbcconfdescriptorDerbyDictionaryBeantitle.html)
 I have to activate it somehow.

Does Derby supports query timeout at all? If so, can you please point me to 
some references ?
Thanks in advance for any help,
Marco




Reply via email to