I'm working on a project for my programming class and the teacher encourages to use stackoverflow for assistance. My problem is as follows: in my if with sResult.next() is coming back false. I'm trying to obtain one row from my derby database.
I have verified my productUuid is obtaining a UUID, preparedstatement is active. I have checked that my findAll for the query is working and it is.
The interceptor is supposed to return the class name that is being used.
My query:
private static final String QUERY_02 =
"SELECT oid, product_name, product_desc, product_price, product_sku, product_inv FROM PRODUCT WHERE oid=?";
My UUIDUtils:
public class UUIDUtils {
public static UUID asUuid(byte[] bytes) {
final ByteBuffer bb = ByteBuffer.wrap(bytes);
final long firstLong = bb.getLong();
final long secondLong = bb.getLong();
return new UUID(firstLong, secondLong);
}
public static byte[] asBytes(UUID uuid) {
final ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return bb.array();
}
My singleProduct:
public ProductDTO singleProduct(UUID productUuid) throws MyStoreException {
log().trace("Entered singleProduct()");
ProductDTO sProduct = null;
try (final Connection connection = datasource.getConnection();
final PreparedStatement sPre = connection.prepareStatement(QUERY_02);) {
sPre.setBytes(1, UUIDUtils.asBytes(productUuid));
log().trace("PreparedStatment connection is active: {}", !sPre.isClosed());
log().trace("productUuid passed through ProductQueryImpl: {}" , productUuid);
ResultSet sResult = sPre.executeQuery();
if(sResult.next()) {
sProduct = new ProductDTO(productUuid,
sResult.getString("product_name"),
sResult.getString("product_desc"),
sResult.getDouble("product_price"),
sResult.getString("product_sku"),
sResult.getInt("product_inv"));
}else {
log().error("Product not found");
}
return sProduct;
}catch(final SQLException ex2) {
log().error(ex2.getMessage(), ex2);
throw new MyStoreException(ex2.getMessage());
}
}
My Console:
00:05:04,092 TRACE [ca.sait.mystore.mvc.model.ProductModel] (default task-1) Entered postConstruct()
00:05:04,094 TRACE [ca.sait.mystore.interceptors.LogInterceptors] (default task-1) Entered logInterceptor(context)
00:05:04,094 DEBUG [ca.sait.mystore.interceptors.LogInterceptors] (default task-1) Method Name: singleProduct
00:05:04,094 TRACE [ca.sait.mystore.dao.ProductQueryImpl] (default task-1) Entered singleProduct()
00:05:04,096 TRACE [ca.sait.mystore.dao.ProductQueryImpl] (default task-1) PreparedStatment connection is active: true
00:05:04,096 TRACE [ca.sait.mystore.dao.ProductQueryImpl] (default task-1) productUuid passed through ProductQueryImpl: 00b6d373-af18-54ed-f8c9-7f9d986a834a
00:05:04,097 ERROR [ca.sait.mystore.dao.ProductQueryImpl] (default task-1) Product not found
00:05:04,098 DEBUG [ca.sait.mystore.interceptors.LogInterceptors] (default task-1) Returning Null
00:05:04,098 TRACE [ca.sait.mystore.interceptors.LogInterceptors] (default task-1) Exited logInterceptor(context)
00:05:04,099 TRACE [ca.sait.mystore.mvc.model.ProductModel] (default task-1) Following UUID passed through Model: 00b6d373-af18-54ed-f8c9-7f9d986a834a
00:05:04,099 TRACE [ca.sait.mystore.mvc.model.ProductModel] (default task-1) Exited postConstruct()
Related
I am not asking the question that is already asked here
Failed to convert from type [java.lang.Object[]] to type
My entity look like this :
#Entity
public class DuplicateManagerMetricsRelTagEntity {
#Id
#Column(name = "sn")
String sn;
#Column(name = "clientid")
String clientid;
#Column(name = "ticket_count")
String ticket_count;
public DuplicateManagerMetricsRelTagEntity(String sn, String clientid, String ticket_count) {
this.sn = sn;
this.clientid = clientid;
this.ticket_count = ticket_count;
}
public DuplicateManagerMetricsRelTagEntity() {
}
My controller look like this :
#RequestMapping("/qbr/duplicatemanager/{clientid}/{appid}/{releasetag}/")
#CrossOrigin
public List<DuplicateManagerMetricsRelTagEntity> getAllDuplicateManagerFromReleaseTag(#PathVariable String clientid, #PathVariable String[] appid, #PathVariable String releasetag) {
logger.info("Returing all duplicate managers of client {} appId {} from release tag {} ", clientid, appid, releasetag);
System.out.println("data in controller : " + clientid + " " + appid + " " + releasetag);
return duplicateManagerMetricsService.getAllDuplicateManagerFromReleaseTag(clientid, appid, releasetag);
}
My service look like this :
public List<DuplicateManagerMetricsRelTagEntity> getAllDuplicateManagerFromReleaseTag(String clientid, String[] appid, String releasetag) {
try {
System.out.println("data in service : "+ clientid + " " + appid + " " + releasetag);
return duplicateManagerMetricsRepository.getAllDuplicateManagerfromReleaseTag(clientid, appid, releasetag);
} catch (Exception e) {
logger.error(e);
return new ArrayList<>();
}
}
My Repository look like this :
#Query(value = "select a.sn, a.clientid, a.ticket_count from dbtable as a where a.clientid = ?1 AND a.appid in (?2) AND a.releasetag=?3", nativeQuery = true)
List<DuplicateManagerMetricsRelTagEntity> getAllDuplicateManagerfromReleaseTag(String clientid, String[] appid, String releasetag);
since i am not getting appid data, i was supposed to get[657-001] but it is printing its object and the error i am getting is :
DuplicateManagerMetricsController - Returing all duplicate managers of client 657 appId [657-001] from release tag WIL657.2021.05-001
data in controller : 657 [Ljava.lang.String;#63108943 WIL657.2021.05-001
data in service : 657 [Ljava.lang.String;#63108943 WIL657.2021.05-001
2022-09-02 05:08:54 DEBUG org.hibernate.SQL - select a.sn, a.clientid, a.ticket_count from dbtable as a where a.clientid = ? AND a.appid in (?) AND a.releasetag=?
2022-09-02 05:08:54 WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 933, SQLState: 42000
2022-09-02 05:08:54 ERROR o.h.e.jdbc.spi.SqlExceptionHelper - ORA-00933: SQL command not properly ended
[ERROR] 2022-09-02 05:08:54.566 [http-nio-8080-exec-2] DuplicateManagerMetricsService - org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
This is because you are extracting fields (a.sn, a.clientid, a.ticket_count) which is not a DuplicateManagerMetricsRelTagEntity type. So since you have not asked hibernate to extract the complete object but a few fields(does not matter if your fields are exactly same as the fields in the object) - so hibernate extracts it as Object[] and then is trying to map to DuplicateManagerMetricsRelTagEntity and hence the issue.
You can use: JPA Projection/DTO
In your case you can use JPQL and :
"select a from DuplicateManagerMetricsRelTagEntity a where a.clientid = ?1 AND a.appid in (?2) AND a.releasetag=?3"
Or for native queries you an try:
select * from table_name where conditions;
NOTE: It has been long since I used hibernate or jpa. So the queries might be not completely accurate. Please do check up on the proper syntax. Main idea is to let you know how hibernate understands and tries to map the type. Since you have a,b,c -> Object[] is extracted and cannot be mapped to your entity.
I have a class which creates the camel routes dynamically.
Previously it creates routes through a simple loop, But now I want to make sure all routes are start at the same time. For that I used FutureTask.
Now I got the exception,
java.lang.UnsupportedOperationException: JBAS011859: Naming context is read-only
There is a JNDI registry used in CreateCamelRoute class.
whenever trying to bind object to that, it throws the exception.
How can I make JNDI Registry thread safe?
public StartRoutes(){
List<DestinationTransport> transport = findAll();
FutureTask[] randomNumberTasks = new FutureTask[transport.size()];
for (int i = 0; i < transport.size(); i++) {
Callable callable = new CallableExampleDT(transport.get(i));
randomNumberTasks[i] = new FutureTask(callable);
Thread t = new Thread(randomNumberTasks[i]);
t.start();
}
for (int i = 0; i < transport.size(); i++) {
System.out.println(randomNumberTasks[i].get());
messages.add((String) randomNumberTasks[i].get());
}
}
}
CallableExampleDT
public class CallableExampleDT implements Callable<Object> {
private final Object transport;
public CallableExampleDT(Object transport) {
this.transport = transport;
}
public synchronized Object call() throws Exception {
String status = "";
DestinationTransport t= (DestinationTransport) transport;
try {
route.createRoute(t);
} catch (Exception e) {
e.printStackTrace();
}
Thread.sleep(5000);
if (route.checkRoute(t.id()))
status= LoggingMessage.STARTED;
else
status= LoggingMessage.IS_STOPPED;
return status;
}
AsyncCamelDynamicFTPRoute
public class AsyncCamelDynamicFTPRoute{
DefaultCamelContext defaultCamelContext = null;
private CamelContext context = null;
JndiRegistry jndi = new JndiRegistry();
public synchronized void createRoute(Object object) throws ApplicationException {
DestinationTransport dt= (DestinationTransport) object;
String destinationTransport= dt.id();
if(Objects.isNull(jndi.lookupByName("DYNAMIC_QUEUES_"+dt.getDestinationTransport()))){
defaultCamelContext = new DefaultCamelContext();
defaultCamelContext.setName("DYNAMIC_QUEUES_"+dt.getDestinationTransport());
//getting exception here, while trying to bind
jndi.bind("DYNAMIC_QUEUES_"+dt.getDestinationTransport(), defaultCamelContext);
}
else {
defaultCamelContext = (DefaultCamelContext) jndi.lookup("DYNAMIC_QUEUES_"+dt.getDestinationTransport());
}
context= defaultCamelContext;
context.getProperties().put(Exchange.LOG_DEBUG_BODY_STREAMS, "true");
context.addRoutes(new RouteBuilder() {
/**Code for creating route**/
}
context.start();
}
Log
ERROR [stderr] (Thread-89) java.lang.UnsupportedOperationException: JBAS011859: Naming context is read-only
01:26:57,536 ERROR [stderr] (Thread-89) at org.jboss.as.naming.WritableServiceBasedNamingStore.requireOwner(WritableServiceBasedNamingStore.java:161)
01:26:57,536 ERROR [stderr] (Thread-89) at org.jboss.as.naming.WritableServiceBasedNamingStore.bind(WritableServiceBasedNamingStore.java:66)
01:26:57,536 ERROR [stderr] (Thread-89) at org.jboss.as.naming.NamingContext.bind(NamingContext.java:253)
01:26:57,537 ERROR [stderr] (Thread-89) at org.jboss.as.naming.InitialContext$DefaultInitialContext.bind(InitialContext.java:260)
01:26:57,537 ERROR [stderr] (Thread-89) at org.jboss.as.naming.NamingContext.bind(NamingContext.java:262)
01:26:57,537 ERROR [stderr] (Thread-89) at javax.naming.InitialContext.bind(InitialContext.java:425)
01:26:57,537 ERROR [stderr] (Thread-89) at javax.naming.InitialContext.bind(InitialContext.java:425)
01:26:57,537 ERROR [stderr] (Thread-89) at org.apache.camel.impl.JndiRegistry.bind(JndiRegistry.java:124)
01:26:57,537 ERROR [stderr] (Thread-89) at com.sial.integration.routing.AsyncCamelDynamicFTPRoute.createRoute(AsyncCamelDynamicFTPRoute.java:91)
01:26:57,537 ERROR [stderr] (Thread-89) at com.sial.integration.routing.AsyncCamelDynamicFTPRoute$Proxy$_$$_WeldClientProxy.createRoute(Unknown Source)
01:26:57,537 ERROR [stderr] (Thread-89) at com.sial.integration.api.CallableExampleDT.call(CallableExampleDT.java:27)
01:26:57,537 ERROR [stderr] (Thread-89) at java.util.concurrent.FutureTask.run(FutureTask.java:266)
01:26:57,537 ERROR [stderr] (Thread-89) at java.lang.Thread.run(Thread.java:745)
I am trying to implement a two phase atomic commit or rollback pattern. The steps are:
read database and populate a ui form
enter changes in the form submit for update and application level validate
do one of two actions
a. commit the multiple changes in one transaction
b. rollback the multiple changes to discard
These steps when done with a commit action work well, database read, form populated and updated, changes update the database.
When these steps are done with a rollback action, the behaviour is identical except an exception is thrown at userTransaction.rollback()
[org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorTrackingImpl] (default task-30) HHH000451:
Transaction afterCompletion called by a background thread; delaying afterCompletion processing until the original thread can handle it.
[status=4]
(default task-30) sessionAbort ex org.hibernate.HibernateException: Transaction was rolled back in a different thread!
Why don't I get an exception thrown when I commit? Each submit of the form has its own thread, but I don't see a multithread issue. I am not sure where to focus my investigation next. MySql or Wildfly or JPA/Hibernate?
Versions are:
java version "1.7.0_07"
ejb3
wildfly-8.2.0.Final
mysqladmin Ver 8.42 Distrib 5.5.21, for Linux on x86_64
RichFaces 4.5.4
Using dialect:org.hibernate.dialect.MySQL5Dialect
Sudo code is:
#TransactionManagement(TransactionManagementType.BEAN)
#Stateful(mappedName = "testSession")
#SessionScoped
#TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public class TestSession {
#PersistenceContext(unitName="MySqlXA",type=PersistenceContextType.EXTENDED)
private EntityManager entityManager;
#Resource private UserTransaction userTransaction;
First request/ thread one
userTransaction.begin();
Query query = entityManager.createQuery(sqlQuery);
List<SomeTable> queryResult = (List<SomeTable>)query.getResultList();
populate a SessionScoped ManagedBean
user think time
make updates through the UI and submit
Second request / thread two
TableOneRow tableOneRow = new TableOneRow(someStuff);
TableTwoRow tableTwoRow = entityManager.find(otherStuff);
entityManager.persist(tableOneRow);
entitymanager.merge(tableTwoRow);
Third request / thread three submit for commit
userTransaction.commit();
or Third request / thread three submit for abort
userTransaction.rollback();
Thanks in advance
With further research and experimentation, it looks like the cleanest way to discard a set of updates is to call entityManager.clear().
See below for a log of three tests and the relevant code. The first group of find,update,commit is my baseline of a good update. The second group of find,update,abort results in the HHH000451 exception. The last bit is the abort portion but using EntityManager clear instead.
2017-03-23 16:48:55,425 DEBUG [view.TestPage] (default task-21) find
2017-03-23 16:48:55,426 TRACE [ejb.session.TestPageSession] (default task-21) findNameAddress for addrId 5
2017-03-23 16:48:55,426 TRACE [ejb.session.TestPageSession] (default task-21) entityManager.find
2017-03-23 16:48:55,465 TRACE [ejb.session.TestPageSession] (default task-21) findNameAddress success true
2017-03-23 16:49:49,714 DEBUG [view.TestPage] (default task-24) update
2017-03-23 16:49:49,714 TRACE [ejb.session.TestPageSession] (default task-24) updateFirstLastName to One, For
2017-03-23 16:49:49,715 TRACE [ejb.session.TestPageSession] (default task-24) userTransaction.begin
2017-03-23 16:49:49,716 TRACE [ejb.session.TestPageSession] (default task-24) userTransaction.begin success true
2017-03-23 16:49:49,716 TRACE [ejb.session.TestPageSession] (default task-24) findNameAddress for addrId 5
2017-03-23 16:49:49,716 TRACE [ejb.session.TestPageSession] (default task-24) entityManager.find
2017-03-23 16:49:49,716 TRACE [ejb.session.TestPageSession] (default task-24) findNameAddress success true
2017-03-23 16:49:49,716 TRACE [ejb.session.TestPageSession] (default task-24) entityManager.merge
2017-03-23 16:49:49,721 TRACE [ejb.session.TestPageSession] (default task-24) updateFirstLastName success true
2017-03-23 16:50:19,652 DEBUG [view.TestPage] (default task-25) commit
2017-03-23 16:50:19,654 TRACE [ejb.session.TestPageSession] (default task-25) userTransaction.commit
2017-03-23 16:50:19,726 TRACE [ejb.session.TestPageSession] (default task-25) userTransaction.commit success true
2017-03-23 16:50:50,740 DEBUG [view.TestPage] (default task-26) find
2017-03-23 16:50:50,741 TRACE [ejb.session.TestPageSession] (default task-26) findNameAddress for addrId 5
2017-03-23 16:50:50,741 TRACE [ejb.session.TestPageSession] (default task-26) entityManager.find
2017-03-23 16:50:50,741 TRACE [ejb.session.TestPageSession] (default task-26) findNameAddress success true
2017-03-23 16:51:12,735 DEBUG [view.TestPage] (default task-29) update
2017-03-23 16:51:12,735 TRACE [ejb.session.TestPageSession] (default task-29) updateFirstLastName to two, For
2017-03-23 16:51:12,735 TRACE [ejb.session.TestPageSession] (default task-29) userTransaction.begin
2017-03-23 16:51:12,736 TRACE [ejb.session.TestPageSession] (default task-29) userTransaction.begin success true
2017-03-23 16:51:12,736 TRACE [ejb.session.TestPageSession] (default task-29) findNameAddress for addrId 5
2017-03-23 16:51:12,736 TRACE [ejb.session.TestPageSession] (default task-29) entityManager.find
2017-03-23 16:51:12,736 TRACE [ejb.session.TestPageSession] (default task-29) findNameAddress success true
2017-03-23 16:51:12,736 TRACE [ejb.session.TestPageSession] (default task-29) entityManager.merge
2017-03-23 16:51:12,736 TRACE [ejb.session.TestPageSession] (default task-29) updateFirstLastName success true
2017-03-23 16:51:40,888 DEBUG [view.TestPage] (default task-30) abort
2017-03-23 16:51:40,889 TRACE [ejb.session.TestPageSession] (default task-30) userTransaction.rollback
2017-03-23 16:51:40,890 WARN [org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorTrackingImpl] (default task-30) HHH000451: Transaction afterCompletion called by a background thread; delaying afterCompletion processing until the original thread can handle it. [status=4]
2017-03-23 16:51:40,891 TRACE [ejb.session.TestPageSession] (default task-30) userTransaction.rollback success true
2017-03-23 16:54:08,623 DEBUG [view.TestPage] (default task-12) abort
2017-03-23 16:54:08,624 TRACE [ejb.session.TestPageSession] (default task-12) entityManager.clear
2017-03-23 16:54:08,625 TRACE [ejb.session.TestPageSession] (default task-12) entityManager.clear success true
package com.gregdata.session;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.faces.bean.SessionScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.transaction.UserTransaction;
import org.jboss.logging.Logger;
import com.gregdata.model.Nameaddress;
#TransactionManagement(TransactionManagementType.BEAN)
#Stateful(mappedName = "localTestSession")
#SessionScoped
#TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public class TestPageSession implements TestPageSessionLocal {
#PersistenceContext(unitName="MySqlStocksXA",
type=PersistenceContextType.EXTENDED)
private EntityManager entityManager;
#Resource private UserTransaction userTransaction;
private Nameaddress nameaddress;
private boolean transactionBegun;
private Logger logger;
public TestPageSession() {
logger = Logger.getLogger(this.getClass());
}
#PostConstruct
public void initialize() {
}
public EntityManager getEntityManager() {
return entityManager;
}
public Nameaddress findNameaddress(int addrId)
{
Nameaddress nameaddress = null;
boolean success = false;
logger.trace("findNameAddress for addrId "+addrId);
try {
logger.trace("entityManager.find");
nameaddress = entityManager.find(Nameaddress.class, addrId);
success = true;
} catch (Exception ex)
{
logger.warn("findNameAddress ex: "+ex.getMessage());
success = true;
}
logger.trace("findNameAddress success "+success);
return nameaddress;
}
public boolean updateFirstLastName(int addrId, String firstName, String lastName)
{
boolean success = false;
logger.trace("updateFirstLastName to "+firstName+", "+lastName);
try
{
beginTransaction();
nameaddress = findNameaddress(addrId);
if ( nameaddress == null)
{
throw new Exception("Nameaddress id "+addrId+" not found");
}
nameaddress.setFirstName(firstName);
nameaddress.setLastName(lastName);
logger.trace("entityManager.merge");
entityManager.merge(nameaddress);
success = true;
} catch (Exception ex)
{
logger.warn("updateFirstLastName ex: "+ex.getMessage());
success = false;
}
logger.trace("updateFirstLastName success "+success);
return success;
}
public boolean beginTransaction()
{
boolean success = false;
if (transactionBegun) return true;
logger.trace("userTransaction.begin");
try
{
userTransaction.begin();
success = true;
transactionBegun = true;
} catch(Exception ex)
{
logger.warn("userTransaction.begin ex "+ex.getMessage());
success = false;
}
logger.trace("userTransaction.begin success "+success);
return success;
}
public boolean commitTransaction()
{
boolean success = false;
logger.trace("userTransaction.commit");
try
{
userTransaction.commit();
success = true;
transactionBegun = false;
} catch(Exception ex)
{
logger.warn("userTransaction.commit ex "+ex.getMessage());
success = false;
transactionBegun = false;
}
logger.trace("userTransaction.commit success "+success);
return success;
}
public boolean abortTransaction()
{
boolean success = false;
logger.trace("userTransaction.rollback");
try
{
userTransaction.rollback();
success = true;
transactionBegun = false;
} catch(Exception ex)
{
logger.warn("userTransaction.rollback ex "+ex.getMessage());
transactionBegun = false;
success = false;
}
logger.trace("userTransaction.rollback success "+success);
return success;
}
public boolean clearEntityManager() {
boolean success = false;
logger.trace("entityManager.clear");
try {
entityManager.clear();
success = true;
} catch (Exception ex) {
logger.warn("clearEntityManager ex: "+ex.getMessage());
}
logger.trace("entityManager.clear success "+success);
return success;
}
}
I have completed a "happy-path" (as below).
How I can advise a .transform call to have it invoke an error flow (via errorChannel) w/o interrupting the mainFlow?
Currently the mainFlow terminates on first failure occurrence in second .transform (when payload cannot be deserialized to type). My desired behavior is that I'd like to log and continue processing.
I've read about ExpressionEvaluatingRequestHandlerAdvice. Would I just add a second param to each .transform call like e -> e.advice(myAdviceBean) and declare such a bean with success and error channels? Assuming I'd need to break up my mainFlow to receive success from each transform.
On some commented direction I updated the original code sample. But I'm still having trouble taking this "all the way home".
2015-09-08 11:49:19,664 [pool-3-thread-1] org.springframework.integration.handler.ServiceActivatingHandler DEBUG handler 'ServiceActivator for [org.springframework.integration.dsl.support.BeanNameMessageProcessor#5f3839ad] (org.springframework.integration.handler.ServiceActivatingHandler#0)' produced no reply for request Message: ErrorMessage [payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed; nested exception is org.springframework.integration.transformer.MessageTransformationException: failed to transform message; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "hasDoaCostPriceChanged" (class com.xxx.changehistory.jdbc.data.RatePlanLevelRestrictionLog), not marked as ignorable (18 known properties: "supplierUpdateDate", "fPLOSMaskArrival", "createDate", "endAllowed", "sellStateId", "ratePlanLevel", "ratePlanId", "startAllowed", "stayDate", "doaCostPriceChanged", "hotelId", "logActionTypeId" [truncated]])
at [Source: java.util.zip.GZIPInputStream#242017b8; line: 1, column: 32] (through reference chain: com.xxx.changehistory.jdbc.data.RatePlanLevelRestrictionLog["hasDoaCostPriceChanged"]), headers={id=c054d976-5750-827f-8894-51aba9655c77, timestamp=1441738159660}]
2015-09-08 11:49:19,664 [pool-3-thread-1] org.springframework.integration.channel.DirectChannel DEBUG postSend (sent=true) on channel 'errorChannel', message: ErrorMessage [payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed; nested exception is org.springframework.integration.transformer.MessageTransformationException: failed to transform message; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "hasDoaCostPriceChanged" (class com.xxx.changehistory.jdbc.data.RatePlanLevelRestrictionLog), not marked as ignorable (18 known properties: "supplierUpdateDate", "fPLOSMaskArrival", "createDate", "endAllowed", "sellStateId", "ratePlanLevel", "ratePlanId", "startAllowed", "stayDate", "doaCostPriceChanged", "hotelId", "logActionTypeId" [truncated]])
at [Source: java.util.zip.GZIPInputStream#242017b8; line: 1, column: 32] (through reference chain: com.xxx.changehistory.jdbc.data.RatePlanLevelRestrictionLog["hasDoaCostPriceChanged"]), headers={id=c054d976-5750-827f-8894-51aba9655c77, timestamp=1441738159660}]
2015-09-08 11:49:19,664 [pool-3-thread-1] org.springframework.integration.channel.DirectChannel DEBUG preSend on channel 'mainFlow.channel#3', message: GenericMessage [payload=java.util.zip.GZIPInputStream#242017b8, headers={id=b80106f9-7f4c-1b92-6aca-6e73d3bf8792, timestamp=1441738159664}]
2015-09-08 11:49:19,664 [pool-3-thread-1] org.springframework.integration.aggregator.AggregatingMessageHandler DEBUG org.springframework.integration.aggregator.AggregatingMessageHandler#0 received message: GenericMessage [payload=java.util.zip.GZIPInputStream#242017b8, headers={id=b80106f9-7f4c-1b92-6aca-6e73d3bf8792, timestamp=1441738159664}]
2015-09-08 11:49:19,665 [pool-3-thread-1] org.springframework.integration.channel.DirectChannel DEBUG preSend on channel 'errorChannel', message: ErrorMessage [payload=org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.integration.aggregator.AggregatingMessageHandler#0]; nested exception is java.lang.IllegalStateException: Null correlation not allowed. Maybe the CorrelationStrategy is failing?, headers={id=24e3a1c7-af6b-032c-6a29-b55031fba0d7, timestamp=1441738159665}]
2015-09-08 11:49:19,665 [pool-3-thread-1] org.springframework.integration.handler.ServiceActivatingHandler DEBUG ServiceActivator for [org.springframework.integration.dsl.support.BeanNameMessageProcessor#5f3839ad] (org.springframework.integration.handler.ServiceActivatingHandler#0) received message: ErrorMessage [payload=org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.integration.aggregator.AggregatingMessageHandler#0]; nested exception is java.lang.IllegalStateException: Null correlation not allowed. Maybe the CorrelationStrategy is failing?, headers={id=24e3a1c7-af6b-032c-6a29-b55031fba0d7, timestamp=1441738159665}]
2015-09-08 11:49:19,665 [pool-3-thread-1] com.xxx.DataMigrationModule$ErrorService ERROR org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.integration.aggregator.AggregatingMessageHandler#0]; nested exception is java.lang.IllegalStateException: Null correlation not allowed. Maybe the CorrelationStrategy is failing?
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:84)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:287)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:245)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:95)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:231)
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:154)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:102)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:105)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.access$000(UnicastingDispatcher.java:48)
at org.springframework.integration.dispatcher.UnicastingDispatcher$1.run(UnicastingDispatcher.java:92)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Null correlation not allowed. Maybe the CorrelationStrategy is failing?
at org.springframework.util.Assert.state(Assert.java:385)
at org.springframework.integration.aggregator.AbstractCorrelatingMessageHandler.handleMessageInternal(AbstractCorrelatingMessageHandler.java:369)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
... 22 more
UPDATED (09-08-2015)
code sample
#Bean
public IntegrationFlow mainFlow() {
// #formatter:off
return IntegrationFlows
.from(
amazonS3InboundSynchronizationMessageSource(),
e -> e.poller(p -> p.trigger(this::nextExecutionTime))
)
.transform(unzipTransformer())
.split(f -> new FileSplitter())
.channel(MessageChannels.executor(Executors.newCachedThreadPool()))
.transform(Transformers.fromJson(persistentType()), , e -> e.advice(handlingAdvice()))
// #see http://docs.spring.io/spring-integration/reference/html/messaging-routing-chapter.html#agg-and-group-to
.aggregate(a ->
a.releaseStrategy(g -> g.size() == persistenceBatchSize)
.expireGroupsUponCompletion(true)
.sendPartialResultOnExpiry(true)
.groupTimeoutExpression("size() ge 2 ? 10000 : -1")
, null
)
.handle(jdbcRepositoryHandler())
// TODO add advised PollableChannel to deal with possible persistence issue and retry with partial batch
.get();
// #formatter:on
}
#Bean
public ErrorService errorService() {
return new ErrorService();
}
#Bean
public MessageChannel customErrorChannel() {
return MessageChannels.direct().get();
}
#Bean
public IntegrationFlow customErrorFlow() {
// #formatter:off
return IntegrationFlows
.from(customErrorChannel())
.handle("errorService", "handleError")
.get();
// #formatter:on
}
#Bean
ExpressionEvaluatingRequestHandlerAdvice handlingAdvice() {
ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
advice.setOnFailureExpression("payload");
advice.setFailureChannel(customErrorChannel());
advice.setReturnFailureExpressionResult(true);
advice.setTrapException(true);
return advice;
}
protected class ErrorService implements ErrorHandler {
private final Logger log = LoggerFactory.getLogger(getClass());
#Override
public void handleError(Throwable t) {
stopEndpoints(t);
}
private void stopEndpoints(Throwable t) {
log.error(ExceptionUtils.getStackTrace(t));
}
}
Turns out I had things wrong in a few places, like:
I had to autowire a Jackson2 ObjectMapper (that I get from Sprint Boot auto-config) and construct an instance of JsonObjectMapper to be added as second arg in Transformers.fromJson; made for more lenient unmarshalling to persistent type (stops UnrecognizedPropertyException); and thus waived need for ExpressionEvaluatingRequestHandlerAdvice
Choosing the proper variant of .split method in IntegrationFlowDefinition in order to employ the FileSplitter, otherwise you don't get this splitter rather a DefaultMessageSplitter which pre-maturely terminates flow after first record read from InputStream
Moved transform, aggregate, handle to a its own pubsub channel employing an async task executor
Still not 100% of what I need, but it's much further along.
See what I ended up w/ below...
#Configuration
#EnableIntegration
#IntegrationComponentScan
public class DataMigrationModule {
private final Logger log = LoggerFactory.getLogger(getClass());
#Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
#Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
#Value("${cloud.aws.s3.bucket}")
private String bucket;
#Value("${cloud.aws.s3.max-objects-per-batch:1024}")
private int maxObjectsPerBatch;
#Value("${cloud.aws.s3.accept-subfolders:false}")
private String acceptSubFolders;
#Value("${cloud.aws.s3.remote-directory}")
private String remoteDirectory;
#Value("${cloud.aws.s3.local-directory-ref:java.io.tmpdir}")
private String localDirectoryRef;
#Value("${cloud.aws.s3.local-subdirectory:target/s3-dump}")
private String localSubdirectory;
#Value("${cloud.aws.s3.filename-wildcard:}")
private String fileNameWildcard;
#Value("${app.persistent-type:}")
private String persistentType;
#Value("${app.repository-type:}")
private String repositoryType;
#Value("${app.persistence-batch-size:2500}")
private int persistenceBatchSize;
#Value("${app.persistence-batch-release-timeout-in-milliseconds:5000}")
private int persistenceBatchReleaseTimeoutMillis;
#Autowired
private ListableBeanFactory beanFactory;
#Autowired
private ObjectMapper objectMapper;
private final AtomicBoolean invoked = new AtomicBoolean();
private Class<?> repositoryType() {
try {
return Class.forName(repositoryType);
} catch (ClassNotFoundException cnfe) {
log.error("Unknown repository implementation!", cnfe);
System.exit(0);
}
return null;
}
private Class<?> persistentType() {
try {
return Class.forName(persistentType);
} catch (ClassNotFoundException cnfe) {
log.error("Unsupported type!", cnfe);
System.exit(0);
}
return null;
}
public Date nextExecutionTime(TriggerContext triggerContext) {
return this.invoked.getAndSet(true) ? null : new Date();
}
#Bean
public FileToInputStreamTransformer unzipTransformer() {
FileToInputStreamTransformer transformer = new FileToInputStreamTransformer();
transformer.setDeleteFiles(true);
return transformer;
}
#Bean
public MessageSource<?> amazonS3InboundSynchronizationMessageSource() {
AWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey);
AmazonS3InboundSynchronizationMessageSource messageSource = new AmazonS3InboundSynchronizationMessageSource();
messageSource.setCredentials(credentials);
messageSource.setBucket(bucket);
messageSource.setMaxObjectsPerBatch(maxObjectsPerBatch);
messageSource.setAcceptSubFolders(Boolean.valueOf(acceptSubFolders));
messageSource.setRemoteDirectory(remoteDirectory);
if (!fileNameWildcard.isEmpty()) {
messageSource.setFileNameWildcard(fileNameWildcard);
}
String directory = System.getProperty(localDirectoryRef);
if (!localSubdirectory.startsWith("/")) {
localSubdirectory = "/" + localSubdirectory;
}
if (!localSubdirectory.endsWith("/")) {
localSubdirectory = localSubdirectory + "/";
}
directory = directory + localSubdirectory;
FileUtils.mkdir(directory);
messageSource.setDirectory(new LiteralExpression(directory));
return messageSource;
}
#Bean
public IntegrationFlow mainFlow() {
// #formatter:off
return IntegrationFlows
.from(
amazonS3InboundSynchronizationMessageSource(),
e -> e.poller(p -> p.trigger(this::nextExecutionTime))
)
.transform(unzipTransformer())
.split(new FileSplitter(), null)
.publishSubscribeChannel(new SimpleAsyncTaskExecutor(), p -> p.subscribe(persistenceSubFlow()))
.get();
// #formatter:on
}
#Bean
public IntegrationFlow persistenceSubFlow() {
JsonObjectMapper<?, ?> jsonObjectMapper = new Jackson2JsonObjectMapper(objectMapper);
ReleaseStrategy releaseStrategy = new TimeoutCountSequenceSizeReleaseStrategy(persistenceBatchSize,
persistenceBatchReleaseTimeoutMillis);
// #formatter:off
return f -> f
.transform(Transformers.fromJson(persistentType(), jsonObjectMapper))
// #see http://docs.spring.io/spring-integration/reference/html/messaging-routing-chapter.html#agg-and-group-to
.aggregate(
a -> a
.releaseStrategy(releaseStrategy)
.correlationStrategy(m -> m.getHeaders().get("id"))
.expireGroupsUponCompletion(true)
.sendPartialResultOnExpiry(true)
, null
)
.handle(jdbcRepositoryHandler());
// #formatter:on
}
#Bean
public JdbcRepositoryHandler jdbcRepositoryHandler() {
return new JdbcRepositoryHandler(repositoryType(), beanFactory);
}
protected class JdbcRepositoryHandler extends AbstractMessageHandler {
#SuppressWarnings("rawtypes")
private Insertable repository;
public JdbcRepositoryHandler(Class<?> repositoryClass, ListableBeanFactory beanFactory) {
repository = (Insertable<?>) beanFactory.getBean(repositoryClass);
}
#Override
protected void handleMessageInternal(Message<?> message) {
repository.insert((List<?>) message.getPayload());
}
}
protected class FileToInputStreamTransformer extends AbstractFilePayloadTransformer<InputStream> {
#Override
protected InputStream transformFile(File payload) throws Exception {
return new GZIPInputStream(new FileInputStream(payload));
}
}
}
Yes, you are correct. To advice the handle() method of Transformer's MessageHandler you should use exactly that e.advice method of the second parameter of .transform() EIP-method. And yes: you should define ExpressionEvaluatingRequestHandlerAdvice bean for your purpose.
You can reuse that Advice bean for different goals to handle successes and failures the same manner.
UPDATE
Although it isn't clear to me how you'd like to continue the flow with the wrong message, but you you can use onFailureExpression and returnFailureExpressionResult=true of the ExpressionEvaluatingRequestHandlerAdvice to return something after the unzipErrorChannel().
BTW the failureChannel logic doesn't work without onFailureExpression:
if (this.onFailureExpression != null) {
Object evalResult = this.evaluateFailureExpression(message, actualException);
if (this.returnFailureExpressionResult) {
return evalResult;
}
}
I've a problem using Hibernate, after executing one of my queries I get the following Log messages and the program stops to work:
20:36:48,805 TRACE ThreadLocalSessionContext:344 - allowing proxied method [createQuery] to proceed to real session
4608 [main] TRACE org.hibernate.context.ThreadLocalSessionContext - allowing proxied method [createQuery] to proceed to real session
20:36:48,806 TRACE QueryPlanCache:128 - located HQL query plan in cache (from Propertylist where typedlistId = ?)
4609 [main] TRACE org.hibernate.engine.query.QueryPlanCache - located HQL query plan in cache (from Propertylist where typedlistId = ?)
In practice I have a small method where I call:
public List<Zielobjekt> gibZielobjekte() {
List<Zielobjekt> zielobjekte = new ArrayList<Zielobjekt>();
Session session = _sessionFactory.getCurrentSession();
session.beginTransaction();
for(Informationsverbund iv : gibInformationsverbuende() /*Behind this method is a Hibernate query, it works fine.*/ )
{
Set<Celement> zobjekte = gibBaumelementeFuerVater(session, iv.getOriginalId());
LOGGER.info("Insgesamt " + zobjekte.size() + " ZO gefunden.");
for(Celement element : zobjekte)
{
Set<Propertylist> eigenschaften = gibEigenschaftsliste(session, element); /*Behind this Method is a Hibernate Query, here the Program stops to work.*/
//HERE THE PROGRAM STOPS WORKING
...
}
}
session.getTransaction().commit();
return zielobjekte;
}
The method called, where the program stops working is:
private Set<Propertylist> gibEigenschaftsliste(Session session, Celement element)
{
try
{
return new HashSet(session.createQuery(
"from Propertylist where typedlistId = ?")
.setInteger(0, element.getEntityId())
.list());
}
catch (HibernateException e)
{
e.printStackTrace();
return null;
}
}