Babak, Thanks for the detailed reply, but if you look at my first post on this thread, I mentioned that that error message concerning enhancement is misleading. If I configure "consumeDelete=false", there's no error - the entities are created by JPA. I also mentioned I verified enhancement by observing the added fields, methods and interfaces via the "javap" (decompiler) tool.
I didn't know about the test-enhance goal, so that was good to learn, thanks. (my entities are under main/java, so I just use the "enhance" goal) -Chris On Tue, Jan 15, 2013 at 4:05 PM, Babak Vahdat <[email protected]> wrote: > > > Am 15.01.13 21:22 schrieb "Chris Wolf" unter <[email protected]>: > >>I upgraded to OpenJPA-2.2.1. Still have the same issue. > > Hi > > The problem you're facing is that the byte-code of your JPA entity has not > been enhanced, see your stack trace where it says "Ensure that it has been > enhanced." Also take a look at the source where that exception is thrown: > > org.apache.openjpa.kernel.BrokerImpl.assertPersistenceCapable(BrokerImpl.ja > va:4667) > > When enhancement gets done properly then the byte code of your entity > class gets instrumentalized to implement the interface > org.apache.openjpa.enhance.PersistenceCapable (this's of course in case of > OpenJPA). > > No matter which JPA provider you make use of (OpenJPA, Hibernate or > Eclipselink) @ runtime you should make sure that the entity class byte > code has been enhanced/weaved properly. This can be done either statically > or dynamically. Recently I added a note about this on the Camel JPA > component documentation which could be helpful for your use case. See the > blue box at the bottom here: > > http://camel.apache.org/jpa.html > > In that box there's also a link pointing to the corresponding OpenJPA > documentation about this. You can also look at the camel-jpa POM itself to > see how the static enhancement is done. However in your case you would > need to make use of the "enhance" goal and not "test-enhance". > > Babak > >> >> >> >>Here's the route, followed by console output, followed by entities >>code. BTW, I notice that the data type of Body coming out >>of the jpa endpoint is of type Object[], I think this is part of the >>problem, because I put a breakpoint on line 159 in JpaConsumer, >>which is: >> >>getDeleteHandler().deleteObject(entityManager, result); >> >>...and that "result" is of type Object[] where each element is a >>field value of the entity cooresponding to the >>MarketData entity but it's NOT of type MarketData - hence the cast >>exception when EntityManager.remove() is called. >> >>Thanks Claus and Christian, >> >> -Chris >> >> >> >> >> >>from("jpa:entities.MarketData?persistenceUnit=marketdata&consumeDelete=tru >>e&consumer.nativeQuery=select >>* from market_data where rownum < 10") >> >>.to("log:test.camel?showAll=true&multiline=true&level=INFO") >> .to("mock:foo"); >> >>1158 marketdata INFO [Camel (camel-1) thread #1 - >>jpa://entities.MarketData] openjpa.Runtime - Starting OpenJPA 2.2.1 >>1236 marketdata INFO [Camel (camel-1) thread #1 - >>jpa://entities.MarketData] openjpa.jdbc.JDBC - Using dictionary class >>"org.apache.openjpa.jdbc.sql.OracleDictionary". >>3661 [Camel (camel-1) thread #1 - jpa://entities.MarketData] INFO >>test.camel - Exchange[ >>, Id:ID-cwolf-55710-1358279796309-0-2 >>, ExchangePattern:InOnly >>, >>Properties:{CamelToEndpoint=log://test.camel?level=INFO&multiline=true&sho >>wAll=true, >>CamelBatchComplete=true, CamelBatchSize=1, CamelCreatedTimestamp=Tue >>Jan 15 14:56:39 EST 2013, CamelBatchIndex=0} >>, >>Headers:{CamelJpaTemplate=org.springframework.orm.jpa.JpaTemplate@1e99db4, >>breadcrumbId=ID-cwolf-55710-1358279796309-0-1} >>, BodyType:Object[] >>, Body:[Ljava.lang.Object;@a1e2da >>, Out: null >>] >>3272 [Camel (camel-1) thread #1 - jpa://entities.MarketData] WARN >>org.apache.camel.component.jpa.JpaConsumer - Error processing last >>message due: <openjpa-2.2.1-r422266:1396819 nonfatal user error> >>org.apache.openjpa.persistence.ArgumentException: Attempt to cast >>instance "[Ljava.lang.Object;@1cfd3b2" to PersistenceCapable failed. >>Ensure that it has been enhanced. >>FailedObject: [Ljava.lang.Object;@1cfd3b2. Will commit all previous >>successful processed message, and ignore this last failure. >>javax.persistence.PersistenceException: <openjpa-2.2.1-r422266:1396819 >>nonfatal user error> org.apache.openjpa.persistence.ArgumentException: >>Attempt to cast instance "[Ljava.lang.Object;@1cfd3b2" to >>PersistenceCapable failed. Ensure that it has been enhanced. >>FailedObject: [Ljava.lang.Object;@1cfd3b2 >> at >>org.apache.camel.component.jpa.JpaConsumer$1.doInJpa(JpaConsumer.java:102) >> at >>org.apache.camel.component.jpa.JpaTemplateTransactionStrategy$1$1.doInJpa( >>JpaTemplateTransactionStrategy.java:82) >> at >> org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:183) >> at >> org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:146) >> at >>org.apache.camel.component.jpa.JpaTemplateTransactionStrategy$1.doInTransa >>ction(JpaTemplateTransactionStrategy.java:80) >> at >>org.springframework.transaction.support.TransactionTemplate.execute(Transa >>ctionTemplate.java:130) >> at >>org.apache.camel.component.jpa.JpaTemplateTransactionStrategy.execute(JpaT >>emplateTransactionStrategy.java:78) >> at org.apache.camel.component.jpa.JpaConsumer.poll(JpaConsumer.java:75) >> at >>org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.ja >>va:139) >> at >>org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java >>:91) >> at >>java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) >> at >>java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317) >> at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150) >> at >>java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.acces >>s$101(ScheduledThreadPoolExecutor.java:98) >> at >>java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPe >>riodic(ScheduledThreadPoolExecutor.java:180) >> at >>java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(S >>cheduledThreadPoolExecutor.java:204) >> at >>java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor. >>java:886) >> at >>java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java >>:908) >> at java.lang.Thread.run(Thread.java:662) >>Caused by: <openjpa-2.2.1-r422266:1396819 nonfatal user error> >>org.apache.openjpa.persistence.ArgumentException: Attempt to cast >>instance "[Ljava.lang.Object;@1cfd3b2" to PersistenceCapable failed. >>Ensure that it has been enhanced. >>FailedObject: [Ljava.lang.Object;@1cfd3b2 >> at >>org.apache.openjpa.kernel.BrokerImpl.assertPersistenceCapable(BrokerImpl.j >>ava:4667) >> at >>org.apache.openjpa.kernel.BrokerImpl.cascadeTransient(BrokerImpl.java:2683 >>) >> at org.apache.openjpa.kernel.BrokerImpl.delete(BrokerImpl.java:2771) >> at org.apache.openjpa.kernel.BrokerImpl.delete(BrokerImpl.java:2742) >> at >>org.apache.openjpa.kernel.DelegatingBroker.delete(DelegatingBroker.java:11 >>02) >> at >>org.apache.openjpa.persistence.EntityManagerImpl.remove(EntityManagerImpl. >>java:730) >> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >> at >>sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java: >>39) >> at >>sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorIm >>pl.java:25) >> at java.lang.reflect.Method.invoke(Method.java:597) >> at >>org.springframework.orm.jpa.JpaTemplate$CloseSuppressingInvocationHandler. >>invoke(JpaTemplate.java:425) >> at $Proxy14.remove(Unknown Source) >> at >>org.apache.camel.component.jpa.JpaConsumer$3.deleteObject(JpaConsumer.java >>:337) >> at >>org.apache.camel.component.jpa.JpaConsumer.processBatch(JpaConsumer.java:1 >>59) >> at >>org.apache.camel.component.jpa.JpaConsumer$1.doInJpa(JpaConsumer.java:97) >> ... 18 more >> >> >>Here is the parent entity (which has collection of child entities) >> >>package entities; >> >>import java.io.Serializable; >>import javax.persistence.*; >>import java.math.BigDecimal; >>import java.util.Date; >>import java.util.Set; >> >> >>/** >> * The persistent class for the MARKET_DATA database table. >> * >> */ >>@Entity >>@Table(name="MARKET_DATA") >>public class MarketData implements Serializable { >> private static final long serialVersionUID = 1L; >> private long marketDataId; >> private String currencyCode; >> private Date dataDate; >> private BigDecimal lastPrice; >> private BigDecimal lastUpdatedPrice; >> private String name; >> private String requestId; >> private String requestIdType; >> private String subType; >> private String type; >> private String vendorId; >> private String vendorName; >> private Set<RiskFactor> riskFactors; >> >> public MarketData() { >> } >> >> >> @Id >> @SequenceGenerator(name="MARKET_DATA_MARKETDATAID_GENERATOR", >>sequenceName="MARKET_DATA_ID_SEQ") >> @GeneratedValue(strategy=GenerationType.SEQUENCE, >>generator="MARKET_DATA_MARKETDATAID_GENERATOR") >> @Column(name="MARKET_DATA_ID", unique=true, nullable=false, >> precision=19) >> public long getMarketDataId() { >> return this.marketDataId; >> } >> >> public void setMarketDataId(long marketDataId) { >> this.marketDataId = marketDataId; >> } >> >> >> @Column(name="CURRENCY_CODE", length=3) >> public String getCurrencyCode() { >> return this.currencyCode; >> } >> >> public void setCurrencyCode(String currencyCode) { >> this.currencyCode = currencyCode; >> } >> >> >> @Temporal( TemporalType.DATE) >> @Column(name="DATA_DATE") >> public Date getDataDate() { >> return this.dataDate; >> } >> >> public void setDataDate(Date dataDate) { >> this.dataDate = dataDate; >> } >> >> >> @Column(name="LAST_PRICE", precision=20, scale=4) >> public BigDecimal getLastPrice() { >> return this.lastPrice; >> } >> >> public void setLastPrice(BigDecimal lastPrice) { >> this.lastPrice = lastPrice; >> } >> >> >> @Column(name="LAST_UPDATED_PRICE", precision=20, scale=4) >> public BigDecimal getLastUpdatedPrice() { >> return this.lastUpdatedPrice; >> } >> >> public void setLastUpdatedPrice(BigDecimal lastUpdatedPrice) { >> this.lastUpdatedPrice = lastUpdatedPrice; >> } >> >> >> @Column(length=100) >> public String getName() { >> return this.name; >> } >> >> public void setName(String name) { >> this.name = name; >> } >> >> >> @Column(name="REQUEST_ID", length=50) >> public String getRequestId() { >> return this.requestId; >> } >> >> public void setRequestId(String requestId) { >> this.requestId = requestId; >> } >> >> >> @Column(name="REQUEST_ID_TYPE", length=20) >> public String getRequestIdType() { >> return this.requestIdType; >> } >> >> public void setRequestIdType(String requestIdType) { >> this.requestIdType = requestIdType; >> } >> >> >> @Column(name="SUB_TYPE", length=100) >> public String getSubType() { >> return this.subType; >> } >> >> public void setSubType(String subType) { >> this.subType = subType; >> } >> >> >> @Column(name="\"TYPE\"", length=100) >> public String getType() { >> return this.type; >> } >> >> public void setType(String type) { >> this.type = type; >> } >> >> >> @Column(name="VENDOR_ID", length=50) >> public String getVendorId() { >> return this.vendorId; >> } >> >> public void setVendorId(String vendorId) { >> this.vendorId = vendorId; >> } >> >> >> @Column(name="VENDOR_NAME", length=100) >> public String getVendorName() { >> return this.vendorName; >> } >> >> public void setVendorName(String vendorName) { >> this.vendorName = vendorName; >> } >> >> >> //bi-directional many-to-many association to RiskFactor >> @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, >>CascadeType.REFRESH}) >> @JoinTable( >> name="MARKET_DATA_RISK_FACTOR" >> , joinColumns={ >> @JoinColumn(name="MARKET_DATA_ID", nullable=false) >> } >> , inverseJoinColumns={ >> @JoinColumn(name="RISK_FACTOR_ID", nullable=false) >> } >> ) >> public Set<RiskFactor> getRiskFactors() { >> return this.riskFactors; >> } >> >> public void setRiskFactors(Set<RiskFactor> riskFactors) { >> this.riskFactors = riskFactors; >> } >>} >> >> >> >>package entities; >> >>import java.io.Serializable; >>import javax.persistence.*; >>import java.math.BigDecimal; >>import java.util.Date; >>import java.util.Set; >> >> >>/** >> * The persistent class for the RISK_FACTOR database table. >> * >> */ >>@Entity >>@Table(name="RISK_FACTOR") >>public class RiskFactor implements Serializable { >> private static final long serialVersionUID = 1L; >> private long riskFactorId; >> private Date dataDate; >> private String name; >> private BigDecimal seq; >> private BigDecimal seq2; >> private String type; >> private BigDecimal value; >> private BigDecimal value2; >> private Set<MarketData> marketData; >> >> public RiskFactor() { >> } >> >> >> @Id >> @SequenceGenerator(name="RISK_FACTOR_RISKFACTORID_GENERATOR", >>sequenceName="RISK_FACTOR_ID_SEQ") >> @GeneratedValue(strategy=GenerationType.SEQUENCE, >>generator="RISK_FACTOR_RISKFACTORID_GENERATOR") >> @Column(name="RISK_FACTOR_ID", unique=true, nullable=false, >> precision=19) >> public long getRiskFactorId() { >> return this.riskFactorId; >> } >> >> public void setRiskFactorId(long riskFactorId) { >> this.riskFactorId = riskFactorId; >> } >> >> >> @Temporal( TemporalType.DATE) >> @Column(name="DATA_DATE") >> public Date getDataDate() { >> return this.dataDate; >> } >> >> public void setDataDate(Date dataDate) { >> this.dataDate = dataDate; >> } >> >> >> @Column(length=100) >> public String getName() { >> return this.name; >> } >> >> public void setName(String name) { >> this.name = name; >> } >> >> >> @Column(precision=1) >> public BigDecimal getSeq() { >> return this.seq; >> } >> >> public void setSeq(BigDecimal seq) { >> this.seq = seq; >> } >> >> >> public BigDecimal getSeq2() { >> return this.seq2; >> } >> >> public void setSeq2(BigDecimal seq2) { >> this.seq2 = seq2; >> } >> >> >> @Column(name="\"TYPE\"", length=100) >> public String getType() { >> return this.type; >> } >> >> public void setType(String type) { >> this.type = type; >> } >> >> >> @Column(name="\"VALUE\"", precision=20, scale=4) >> public BigDecimal getValue() { >> return this.value; >> } >> >> public void setValue(BigDecimal value) { >> this.value = value; >> } >> >> >> @Column(precision=20, scale=4) >> public BigDecimal getValue2() { >> return this.value2; >> } >> >> public void setValue2(BigDecimal value2) { >> this.value2 = value2; >> } >> >> >> //bi-directional many-to-many association to MarketData >> @ManyToMany(mappedBy="riskFactors") >> public Set<MarketData> getMarketData() { >> return this.marketData; >> } >> >> public void setMarketData(Set<MarketData> marketData) { >> this.marketData = marketData; >> } >> >>} >>On Sat, Jan 12, 2013 at 6:31 AM, Christian Müller >><[email protected]> wrote: >>> And by the way, we are using OpenJPA 2.2.1 instead of 2.2.0, which you >>>are >>> using. Can you upgrade? >>> >>> Best, >>> Christian >>> >>> On Fri, Jan 11, 2013 at 8:23 PM, Chris Wolf <[email protected]> >>>wrote: >>> >>>> I have a JPA endpoint setup as a consumer, just performing a basic >>>> query. If I have consumeDelete=false configured, >>>> then it works and I see the entities. When consumeDelete=false is not >>>> configured (default is to remove), then the error >>>> occurs upon JpaTemplate calling EntityManagerImpl.remove(arg) - but >>>> "arg" is of type Object[] - not the entity. >>>> >>>> Second issue is I'd like the route to just perform the query once. >>>> As it is, invokes the query in a loop. >>>> >>>> Thanks >>>> >>>> Chris >>>> >>>> P.S. the EntityManagerImpl.remove(arg) issue is not due to the >>>> entities not being enhanced - I verified that with javap. >>>> >>>> FailedObject: [Ljava.lang.Object;@1e3a0ec. Will commit all previous > >
