Hi Rick,

thanks for taking the time to reply.
I have looked at the link you provide: the method that sets the values in 
persistence.xml should affect all queries attached to that persistence unit; 
the second ("Setting the Query timeout on the single Query") method is the one 
I am using, while the third option is, AFAIK, out of scope in my case.

Marco.

On Apr 20 2022, at 4:46 pm, Rick Hillegas <rick.hille...@gmail.com> wrote:
> 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