I didn’t because it works with Postgres jdbc. I’ll try with other databases/jdbc drivers not sure if that can help
Il giorno mer 20 apr 2022 alle 18:08 Rick Hillegas <rick.hille...@gmail.com> ha scritto: > That suggests to me that the problem is not in the Derby layer. The > problem is in JPA's support for Derby. JPA should be able to take > advantage of java.sql.Statement.setQueryTimeout(). Have you brought this > issue to the JPA community? > > On 4/20/22 7:52 AM, Marco Ferretti wrote: > > 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 > >>>>>>>> > > > > -- Sent from Gmail Mobile