SimpleJdbcCall works calling n-times StoredProcedure then throws error - spring

I've the next error:
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.core.simple.SimpleJdbcCall - JdbcCall call not compiled before execution - invoking compile
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.datasource.DataSourceUtils - Registering transaction synchronization for JDBC Connection
[http-thread-pool-8080(5)] DEBUG o.s.j.c.m.CallMetaDataProviderFactory - Using org.springframework.jdbc.core.metadata.SqlServerCallMetaDataProvider
[http-thread-pool-8080(5)] DEBUG o.s.j.c.m.CallMetaDataProvider - Retrieving metadata for BATABASE/dbo/PA_INSERT
[http-thread-pool-8080(5)] WARN o.s.j.c.m.CallMetaDataProvider - Error while retrieving metadata for procedure columns: com.microsoft.sqlserver.jdbc.SQLServerException: Could not find prepared statement with handle 41.
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.core.simple.SimpleJdbcCall - Compiled stored procedure. Call string is [{call DATABASE.dbo.PA_INSERT()}]
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.core.simple.SimpleJdbcCall - SqlCall for procedure [PA_ISolicitudDistincion] compiled
[http-thread-pool-8080(5)] DEBUG o.s.j.c.m.CallMetaDataContext - Matching [COLUMN1, COLUMN2, COLUMN3] with []
[http-thread-pool-8080(5)] DEBUG o.s.j.c.m.CallMetaDataContext - Found match for []
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.core.simple.SimpleJdbcCall - The following parameters are used for call {call DATABASE.dbo.PA_INSERT()} with: {}
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.core.JdbcTemplate - Calling stored procedure [{call DATABASE.dbo.PA_INSERT()}]
[http-thread-pool-8080(5)] INFO o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
[http-thread-pool-8080(5)] INFO o.s.j.support.SQLErrorCodesFactory - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
[http-thread-pool-8080(5)] DEBUG o.s.j.support.SQLErrorCodesFactory - Looking up default SQLErrorCodes for DataSource [com.sun.gjc.spi.jdbc40.DataSource40#12ea240]
[http-thread-pool-8080(5)] DEBUG o.s.j.support.SQLErrorCodesFactory - Database product name cached for DataSource [com.sun.gjc.spi.jdbc40.DataSource40#12ea240]: name is 'Microsoft SQL Server'
[http-thread-pool-8080(5)] DEBUG o.s.j.support.SQLErrorCodesFactory - SQL error codes for 'Microsoft SQL Server' found
[http-thread-pool-8080(5)] DEBUG o.s.j.s.SQLErrorCodeSQLExceptionTranslator - Unable to translate SQLException with Error code '201', will now try the fallback translator
[http-thread-pool-8080(5)] DEBUG o.s.j.s.SQLStateSQLExceptionTranslator - Extracted SQL state class 'S0' from value 'S0004'
[http-thread-pool-8080(5)] DEBUG o.s.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
But, it's strange, because, the same SP works without errors, but when is called N-times throws the error.
I'm using Spring with a pooled connection through Glassfish 3.1.2. to a Sqlserver 2005 database.
Here is the java function
public int registrar(Object1 p,
Object2 d)
{
try
{
final SimpleJdbcCall jdbcCall = (SimpleJdbcCall) context
.getBean("insert");
jdbcCall.setCatalogName("DATABASE");
jdbcCall.setSchemaName("dbo");
final MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("COLUMN1", p.get1());
params.addValue("COLUMN2", p.get1());
params.addValue("COLUMN3", d.get2());
final Map<String, Object> execute = jdbcCall.execute(params);
return (Integer) execute.get("IDENTITY");
}
catch (DataAccessException e)
{
return null;
}
}

It looks like that you are sharing your "insert" - bean among threads. Try using scope="prototype" on your insert bean, so you make sure that you are getting a new instance for each call.

Related

Not fetch a LAZY relation if I call from a method which calls after another Transactional method

In my Spring Boot 2.2.5.RELEASE application I have a problem when I try to fetch a LAZY field.
The problem occurs in a service method, createWayBillFromInvoice, which marked as #Transactional.
Case A: I call this method from a controller directly it executes with no problem.
Case B: I call the same method from another service method which is not itself Transactional
my LAZY fields not fetch.
So I assume it is about Transaction management but I could not find the reason.
The method where my LAZY fields not fetched (and fetched in a direct-call):
#Transactional
public createWayBillFromInvoice(){
Invoice invoice = invoiceRepository.getInvoice(invoiceId);//invoice is selected
Order order = invoice.getOrder();
}
Here my order relation is not null but not initialized and not proxied, so If I call order.getOtherRelations it returns empty.
In case B I call something like:
public void create(){ //This method IS NOT Transactional
invoiceService.createInvoice();//This method is Transactional
waybillService.createWaybilFromInvoice();//The method declared above
}
I tried:
Make the create method Transactional
Set propagation to REQUIRES_NEW for createWaybillFromInvoice
Here are some logs:
2020-06-04 17:17:16.337 DEBUG 1208 --- [nio-9002-exec-4] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [io.salesart.billingservice.service.impl.WaybillServiceImpl.createWayBillFromInvoice]:
2020-06-04 17:17:16.376 DEBUG 1208 --- [nio-9002-exec-4] o.s.jdbc.datasource.DataSourceUtils : Changing isolation level of JDBC Connection [HikariProxyConnection#2044564149 wrapping org.postgresql.jdbc.PgConnection#27db45f] to 2
2020-06-04 17:17:16.450 DEBUG 1208 --- [nio-9002-exec-4] o.h.e.t.internal.TransactionImpl : On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
2020-06-04 17:17:16.451 DEBUG 1208 --- [nio-9002-exec-4] o.h.e.t.internal.TransactionImpl : begin
2020-06-04 17:17:16.451 DEBUG 1208 --- [nio-9002-exec-4] org.postgresql.jdbc.PgConnection : setAutoCommit = false
2020-06-04 17:17:16.457 DEBUG 1208 --- [nio-9002-exec-4] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#caf1ee0]
2020-06-04 17:17:19.532 DEBUG 1208 --- [nio-9002-exec-4] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1021250378<open>)] for JPA transaction

How can I confirm that Spring Transactions are working properly?

I working on an Spring 3.2 application running in OC4j. I have a number of methods annotated with Spring's #Transactional annotation as follows:
// in MyServiceImpl
#Transactional()
public void insertPaymentData(PaymentParams paymentParams) {
// call to MyDaoImpl which in turn calls a
// Spring JDBC Stored Procedure implementation
}
// in the Stored Procedure implementation
#Transactional(propagation = Propagation.MANDATORY)
public void insertPaymentData(PaymentParams paymentParams) {
// execute procedure here
}
In the logs for my local OC4J instance I see entries such as the following which make me think that Transactions are configured correctly:
[1.2.3.4-user123] 2019-03-20 17:36:14,805 DEBUG AbstractFallbackTransactionAttributeSource::getTransactionAttribute - Adding transactional method 'MyServiceImpl.insertPaymentData' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_1800; ''
[1.2.3.4-user123] 2019-03-20 17:36:14,809 DEBUG AbstractBeanFactory::doGetBean - Returning cached instance of singleton bean 'transactionManager'
[1.2.3.4-user123] 2019-03-20 17:36:14,812 DEBUG AbstractPlatformTransactionManager::getTransaction - Creating new transaction with name [my.app.service.payments.MyServiceImpl.insertPaymentData]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_1800; ''
[1.2.3.4-user123] 2019-03-20 17:36:14,821 DEBUG AbstractBeanFactory::doGetBean - Returning cached instance of singleton bean 'transactionManager'
[1.2.3.4-user123] 2019-03-20 17:36:14,822 DEBUG AbstractPlatformTransactionManager::handleExistingTransaction - Participating in existing transaction
[1.2.3.4-user123] 2019-03-20 17:36:14,822 DEBUG DataSourceUtils::doGetConnection - Fetching JDBC Connection from DataSource
[1.2.3.4-user123] 2019-03-20 17:36:14,823 DEBUG DataSourceUtils::doGetConnection - Registering transaction synchronization for JDBC Connection
[1.2.3.4-user123] 2019-03-20 17:38:42,550 DEBUG DataSourceUtils::doReleaseConnection - Returning JDBC Connection to DataSource
[1.2.3.4-user123] 2019-03-20 17:38:42,551 DEBUG AbstractPlatformTransactionManager::processCommit - Initiating transaction commit
Sometimes I see timeout and rollback messages there too.
However when I deploy to the development server provided by the ops department I do not see any messages like this in the logs, although the DEBUG level messages are displayed there too. I added in the following logging lines which I found somewhere on stack overflow:
logger.debug("Transaction name=" + TransactionSynchronizationManager.getCurrentTransactionName());
logger.debug("isActualTransactionActive=" + TransactionSynchronizationManager.isActualTransactionActive());
logger.debug("isSynchronizationActive=" + TransactionSynchronizationManager.isSynchronizationActive());
In the logs I now see things like this:
Transaction name=my.app.service.payments.MyServiceImpl.insertPaymentData
isActualTransactionActive=true
isSynchronizationActive=true
Are these values from TransactionSynchronizationManager telling me anything useful?
Is it telling me that transactions are working fine and to stop worrying?
I have the following in a Spring configuration file:
#Configuration
#EnableTransactionManagement
public class TransactionConfig {
#Bean
public JtaTransactionManager transactionManager() {
return new JtaTransactionManager();
}
}
And I have the following in a spring xml config file:
<tx:annotation-driven transaction-manager="transactionManager" />
Thanks!

Update native query is too slow

I am using Hibernate with native query to update a field in a table with 17000 rows in Oracle.
When I execute the query on Toad, it takes 0.5s to be executed and with the below code no finish ever.
Query query = em.createNativeQuery("UPDATE table SET field= LEAST(NUMERADOR/DENOMINADO, ? )");
query.setParameter(1, value);
query.executeUpdate();
This is the trace:
10-08 14:15:59 DEBUG JpaTransactionManager - Creating new transaction with name [es.package.app.repository.jpa.JPAValorMaximo.update]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
10-08 14:15:59 DEBUG JpaTransactionManager - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl#405264e8] for JPA transaction
10-08 14:15:59 DEBUG AbstractTransactionImpl - begin
10-08 14:15:59 DEBUG LogicalConnectionImpl - Obtaining JDBC connection
10-08 14:15:59 DEBUG LogicalConnectionImpl - Obtained JDBC connection
10-08 14:15:59 DEBUG JdbcTransaction - initial autocommit status: true
10-08 14:15:59 DEBUG JdbcTransaction - disabling autocommit
10-08 14:15:59 DEBUG JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#1bbb3b9e]
10-08 14:15:59 DEBUG SQL - UPDATE table SET field= LEAST(NUMERADOR/DENOMINADO, ? )
Hibernate: UPDATE table SET field= LEAST(NUMERADOR/DENOMINADO, ? )
thanks

HttpRequestMethodNotSupportedException: Request method 'POST' not supported

Creating a unit test with MockMvc I am running into:
HttpRequestMethodNotSupportedException: Request method 'POST' not supported
Which causes the test case to fail expecting a '200' but getting a '405'. Some of the additional things you may see in the Junit are for Spring Rest Docs and can be ignored. Such as the #Rule or the .andDo() on the mockMvc Call. I have followed the following documentation Spring Rest Docs - Path Parameter and cannot seem to get it working.
Here is the Controller:
#RestController("/transferObjects")
public class TransferObjectController {
#RequestMapping(method=RequestMethod.GET, produces="application/json")
public List<TransferObject> getTransferObjects(){
// do some magic
return null;
}
#RequestMapping(value = "/{name}", method=RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
public void addTransferObject(#PathVariable("name")String name){
// do magic
}
#RequestMapping(value = "/{name}", method=RequestMethod.DELETE)
#ResponseStatus(HttpStatus.OK)
public void deleteTransferObject(#PathVariable("name")String name){
// do magic
}
Here is the Junit Class:
public class TransferObjectControllerTest {
#Rule
public RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders.standaloneSetup(new TransferObjectController())
.apply(documentationConfiguration(this.restDocumentation))
.build();
}
#Test
public void testAddTransferObject() throws Exception {
this.mockMvc.perform(post("/transferObjects/{name}", "hi"))
.andExpect(status().isOk()).andDo(document("transferObject",
pathParameters(
parameterWithName("name").description("The name of the new Transfer Object to be created."))));
}
And here is the console while running the test:
11:20:48.148 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerAdapter - Looking for #ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext#5ab785fe
11:20:48.205 [main] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Looking for exception mappings: org.springframework.test.web.servlet.setup.StubWebApplicationContext#5ab785fe
11:20:48.283 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Initializing servlet ''
11:20:48.307 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [servletConfigInitParams] PropertySource with lowest search precedence
11:20:48.307 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [servletContextInitParams] PropertySource with lowest search precedence
11:20:48.312 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
11:20:48.312 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
11:20:48.313 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Initialized StandardServletEnvironment with PropertySources [servletConfigInitParams,servletContextInitParams,systemProperties,systemEnvironment]
11:20:48.313 [main] INFO o.s.mock.web.MockServletContext - Initializing Spring FrameworkServlet ''
11:20:48.313 [main] INFO o.s.t.w.s.TestDispatcherServlet - FrameworkServlet '': initialization started
11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided
11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using LocaleResolver [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver#63238bf4]
11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using ThemeResolver [org.springframework.web.servlet.theme.FixedThemeResolver#32b97305]
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using RequestToViewNameTranslator [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator#2d2e6747]
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using FlashMapManager [org.springframework.web.servlet.support.SessionFlashMapManager#417e7d7d]
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Published WebApplicationContext of servlet '' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.]
11:20:48.319 [main] INFO o.s.t.w.s.TestDispatcherServlet - FrameworkServlet '': initialization completed in 6 ms
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Servlet '' configured successfully
11:20:48.361 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - DispatcherServlet with name '' processing POST request for [/transferObjects/hi]
11:20:48.364 [main] DEBUG o.s.t.w.s.s.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - Looking up handler method for path /transferObjects/hi
11:20:48.368 [main] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
11:20:48.369 [main] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
11:20:48.369 [main] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
11:20:48.369 [main] WARN o.s.web.servlet.PageNotFound - Request method 'POST' not supported
11:20:48.370 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Null ModelAndView returned to DispatcherServlet with name '': assuming HandlerAdapter completed request handling
11:20:48.370 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Successfully completed request
It appears I was able to fix this problem.
Taking a closer look at the console while running the test I noticed:
Mapped "{[],methods=[GET],produces=[application/json]}" onto public java.util.List<common.to.TransferObject> sf.common.controller.TransferObjectController.getTransferObjects()
Mapped "{[/{name}],methods=[POST]}" onto public void sf.common.controller.TransferObjectController.addTransferObject(java.lang.String)
Mapped "{[/{name}],methods=[DELETE]}" onto public void sf.common.controller.TransferObjectController.deleteTransferObject(java.lang.String)
this shows that it is mapping the controller request mappings to the specific RequestMapping the method holds. #RestController("/transferObjects") is not actually defining the mapping as a parent. For me to do that I must include #RequestMapping("/transferObjects") underneath the #RestController.
So by changing the parent mapping I can now use the following test case:
#Test
public void testAddTransferObject() throws Exception {
this.mockMvc.perform(post("/transferObjects/{name}", "hi"))
.andExpect(status().isOk()).andDo(document("transferObject",
pathParameters(
parameterWithName("name").description("The name of the new Transfer Object to be created."))));
}

Spring 3 JDBC transaction manager not working

I am using Spring 3, MYSQL 5.5, tomcat 6. In my app i have 3 DAO methods executing one after another inside a service class method.
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = {
Exception.class, RuntimeException.class })
myService(){
try {
dao1.delete();
dao1.update();
dao1.save();
} catch(){}
}
Dao1 -
delete() throws exp1{ ---- some code ----}
save() throws exp1{ ---- some code ----}
update() throws exp2{ ---- some code ----}
Now even if an exception is raised my transaction gets committed, like if update() raise an exception delete() and save() doesn't get rolledback. I tried looking into spring logs and i can see it has committed transaction after exception
20:00:29,071 DEBUG SQLErrorCodesFactory:198 - Looking up default SQLErrorCodes for DataSource [org.apache.tomcat.dbcp.dbcp.BasicDataSource#44755866]
20:00:29,078 DEBUG SQLErrorCodesFactory:216 - Database product name cached for DataSource [org.apache.tomcat.dbcp.dbcp.BasicDataSource#44755866]: name is 'MySQL'
20:00:29,079 DEBUG SQLErrorCodesFactory:174 - SQL error codes for 'MySQL' found
20:00:29,081 DEBUG SQLErrorCodeSQLExceptionTranslator:399 - Translating SQLException with SQL state '42S02', error code '1146', message [Table 'xxx.xxxx' doesn't exist]; SQL was [DELETE FROM xxxx WHERE xxxx=?] for task [PreparedStatementCallback]
20:00:29,086 DEBUG xxxServiceImpl:1022 - Returning result after deleting product : xxxx.xxxxx.xxxxx.xxx.ResultVO Object {Result: false, Error code: 1016, Error text: Error while deleting data. Please try again later}
20:00:29,094 DEBUG DataSourceTransactionManager:752 - Initiating transaction commit
20:00:29,097 DEBUG DataSourceTransactionManager:264 - Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/xxx?autoReconnect=true, UserName=root#localhost, MySQL-AB JDBC Driver]
20:00:29,113 DEBUG DataSourceTransactionManager:322 - Releasing JDBC Connection [jdbc:mysql://localhost:3306/xxx?autoReconnect=true, UserName=root#localhost, MySQL-AB JDBC Driver] after transaction
20:00:29,115 DEBUG DataSourceUtils:332 - Returning JDBC Connection to DataSource
If i put #Transactionl before DAO methods, transaction gets rolledback but i am getting 500 error, stating that transaction is already marked for rollback. Am i missing something here?
Remove the try {} catch {} block.
The transaction rollback will happen only if the exception is thrown back to the caller from the method.
In your case you are silently killing the exception using a empty try..catch block, so the exception is never propagated to the transaction manager, so the transaction manger never get the signal to rollback.
In case of annotating the dao, when the exception is thrown from the dao layer, the transaction proxy surrounding the dao method marks the attached transaction (created by the service layer) as rollback only, then when the control is returned from the service layer the transaction manager tries to commit the changes but finds that it is marked as read-only. That is why the error is coming.

Resources