Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    JpaDataSource, EMFProviderCMT, @EmbeddedId

    Hi,
    i am integrating SmartGWT (Power 3.0) CMT in my application.

    I have problems in fetching data from a table with a multiple primary key.

    This are the entity bean and the primary key auto-generated class:

    -----------------------------------------------------------------------------------
    @Entity
    @Table(name="xx", schema="xx")
    public class HistoricalPricesEntity implements Serializable {
    private static final long serialVersionUID = 1L;


    @EmbeddedId
    private HistoricalPricesEntityPK id;


    @Column(name="CLOSEPR", nullable=false, precision=16, scale=5)
    private BigDecimal closingPrice;

    @Column(name="P_FILE_ID", nullable=false)
    private int parentFileId;

    .
    .
    .

    @Column(nullable=false, length=1)
    private String status;
    -----------------------------------------------------------------------------------

    -----------------------------------------------------------------------------------
    @Embeddable
    public class HistoricalPricesEntityPK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    @Column(name="INSTR_ID", unique=true, nullable=false)
    private int instrumentId;

    @Column(unique=true, nullable=false)
    private int priceDate;

    @Column(unique=true, nullable=false)
    private int priceTime;

    .
    .
    .
    -----------------------------------------------------------------------------------


    My DataSource is auto-derivated:

    -----------------------------------------------------------------------------------
    <DataSource
    ID="hisPr"
    serverConstructor="com.isomorphic.jpa.JPADataSource"
    autoDeriveSchema="true"
    schemaBean="server.entity.HistoricalPricesEntity"
    >
    -----------------------------------------------------------------------------------



    When fetching, i have the following error:

    [28/08/12 17.25.28:161 CEST] 00000038 SystemOut O === 2012-08-28 17:25:28,161 [ : 6] WARN RequestContext - dsRequest.execute() failed:
    org.apache.openjpa.persistence.ArgumentException: Error in query "select count (_HistoricalPricesEntity.id_priceTime) from HistoricalPricesEntity _HistoricalPricesEntity". Error message: No "id_priceTime" field in class "class server.entity.HistoricalPricesEntity".



    SmartGwt engine is searching a "id_priceTime" field (which doesn't exist) in HistoricalPricesEntity class, not the "priceTime" field in HistoricalPricesEntityPK class.

    What is the problem?
    What is the right configuration to make it works?



    Thanks in advance for your help.



    Giervella
    Last edited by giervella; 28 Aug 2012, 07:50.

    #2
    Ideas?


    Thanks in advance for your help.


    Giervella

    Comment


      #3
      Based on what you've shared, we haven't yet been able to figure out how you could end up with an "id_priceTime" fieldName without some kind of custom code.

      Could you share the complete server log for the failing request (please always do this) as well as the rest of the definition of the PK bean?

      Comment


        #4
        HistoricalPricesEntity.class
        -----------------------------------------------------------------------------------
        @Entity
        @Table(name="HISPR", schema="MYSCHEMA")
        public class HistoricalPricesEntity implements Serializable {
        private static final long serialVersionUID = 1L;


        //***********************************************
        // Manually created foreign keys
        //***********************************************

        // uni-directional many-to-one association to Instr
        @ManyToOne
        @JoinColumn(name="INSTR_ID")
        private InstrumentsEntity instr;

        //***********************************************



        @EmbeddedId
        private HistoricalPricesEntityPK id;


        @Column(name="CLOSEPR", nullable=false, precision=16, scale=5)
        private BigDecimal closingPrice;

        @Column(name="P_FILE_ID", nullable=false)
        private int parentFileId;

        @Column(nullable=false, length=1)
        private String status;

        @Column(name="UPDDATE", nullable=false)
        private Timestamp updateDate;

        @Column(name="UPDTYPE", nullable=false, length=1)
        private String updateType;

        @Column(name="UPDUSR", nullable=false, length=30)
        private String updatingUser;




        public HistoricalPricesEntity() {

        }


        public InstrumentsEntity getInstr() {
        return instr;
        }

        public void setInstr(InstrumentsEntity instr) {
        this.instr = instr;
        }

        public HistoricalPricesEntityPK getId() {
        return this.id;
        }

        public void setId(HistoricalPricesEntityPK id) {
        this.id = id;
        }

        public BigDecimal getClosingPrice() {
        return this.closingPrice;
        }

        public void setClosingPrice(BigDecimal closingPrice) {
        this.closingPrice = closingPrice;
        }

        public int getParentFileId() {
        return this.parentFileId;
        }

        public void setParentFileId(int parentFileId) {
        this.parentFileId = parentFileId;
        }

        public String getStatus() {
        return this.status;
        }

        public void setStatus(String status) {
        this.status = status;
        }

        public Timestamp getUpdateDate() {
        return this.updateDate;
        }

        public void setUpdateDate(Timestamp updateDate) {
        this.updateDate = updateDate;
        }

        public String getUpdateType() {
        return this.updateType;
        }

        public void setUpdateType(String updateType) {
        this.updateType = updateType;
        }

        public String getUpdatingUser() {
        return this.updatingUser;
        }

        public void setUpdatingUser(String updatingUser) {
        this.updatingUser = updatingUser;
        }

        }
        -----------------------------------------------------------------------------------


        HistoricalPricesEntityPK.class
        -----------------------------------------------------------------------------------
        @Embeddable
        public class HistoricalPricesEntityPK implements Serializable {
        //default serial version id, required for serializable classes.
        private static final long serialVersionUID = 1L;

        @Column(name="INSTR_ID", unique=true, nullable=false)
        private int instrumentId;

        @Column(unique=true, nullable=false)
        private int priceDate;

        @Column(unique=true, nullable=false)
        private int priceTime;

        public HistoricalPricesEntityPK() {
        }
        public int getInstrumentId() {
        return this.instrumentId;
        }
        public void setInstrumentId(int instrumentId) {
        this.instrumentId = instrumentId;
        }
        public int getPriceDate() {
        return this.priceDate;
        }
        public void setPriceDate(int priceDate) {
        this.priceDate = priceDate;
        }
        public int getPriceTime() {
        return this.priceTime;
        }
        public void setPriceTime(int priceTime) {
        this.priceTime = priceTime;
        }

        public boolean equals(Object other) {
        if (this.equals( other )) {
        return true;
        }
        if (!(other instanceof HistoricalPricesEntityPK)) {
        return false;
        }
        HistoricalPricesEntityPK castOther = (HistoricalPricesEntityPK)other;
        return
        (this.instrumentId == castOther.instrumentId)
        && (this.priceDate == castOther.priceDate)
        && (this.priceTime == castOther.priceTime);

        }

        public int hashCode() {
        final int prime = 31;
        int hash = 17;
        hash = hash * prime + this.instrumentId;
        hash = hash * prime + this.priceDate;
        hash = hash * prime + this.priceTime;

        return hash;
        }
        }
        -----------------------------------------------------------------------------------



        The complete error log is:

        [31/08/12 10.09.01:788 CEST] 00000021 SystemOut O === 2012-08-31 10:09:01,788 [ : 2] DEBUG JPADataSource - [builtinApplication.fetch] Query string: select _HistoricalPricesEntity, id1 from HistoricalPricesEntity _HistoricalPricesEntity left outer join _HistoricalPricesEntity.id id1

        [31/08/12 10.09.01:866 CEST] 00000021 SystemOut O === 2012-08-31 10:09:01,865 [ : 2] WARN RequestContext - dsRequest.execute() failed:
        <openjpa-1.2.3-SNAPSHOT-r422266:1152904 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Si è verificato un errore durante l'analisi del filtro di query "select count (_HistoricalPricesEntity.id_instrumentId) from HistoricalPricesEntity _HistoricalPricesEntity". Messaggio di errore: Nessun campo denominato "id_instrumentId" nella classe "class it.ccg.infoprovider.server.entity.HistoricalPricesEntity".
        at org.apache.openjpa.kernel.exps.AbstractExpressionBuilder.parseException(AbstractExpressionBuilder.java:118)
        at org.apache.openjpa.kernel.exps.AbstractExpressionBuilder.traversePath(AbstractExpressionBuilder.java:284)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getPath(JPQLExpressionBuilder.java:1382)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getPathOrConstant(JPQLExpressionBuilder.java:1337)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.eval(JPQLExpressionBuilder.java:880)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getValue(JPQLExpressionBuilder.java:1431)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getValue(JPQLExpressionBuilder.java:1417)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.eval(JPQLExpressionBuilder.java:1050)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.eval(JPQLExpressionBuilder.java:1047)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getValue(JPQLExpressionBuilder.java:1431)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getValue(JPQLExpressionBuilder.java:1417)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.assignProjections(JPQLExpressionBuilder.java:325)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.evalSelectClause(JPQLExpressionBuilder.java:435)
        at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getQueryExpressions(JPQLExpressionBuilder.java:274)
        at org.apache.openjpa.kernel.jpql.JPQLParser.eval(JPQLParser.java:62)
        at org.apache.openjpa.kernel.ExpressionStoreQuery$DataStoreExecutor.<init>(ExpressionStoreQuery.java:684)
        at org.apache.openjpa.kernel.ExpressionStoreQuery.newDataStoreExecutor(ExpressionStoreQuery.java:173)
        at org.apache.openjpa.kernel.QueryImpl.createExecutor(QueryImpl.java:734)
        at org.apache.openjpa.kernel.QueryImpl.compileForDataStore(QueryImpl.java:692)
        at org.apache.openjpa.kernel.QueryImpl.compileForExecutor(QueryImpl.java:674)
        at org.apache.openjpa.kernel.QueryImpl.getOperation(QueryImpl.java:1492)
        at org.apache.openjpa.kernel.DelegatingQuery.getOperation(DelegatingQuery.java:123)
        at org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:243)
        at org.apache.openjpa.persistence.QueryImpl.getSingleResult(QueryImpl.java:317)
        at com.isomorphic.jpa.JPADataSource.executeFetch(JPADataSource.java:775)
        at com.isomorphic.datasource.DataSource.execute(DataSource.java:1287)
        at com.isomorphic.jpa.JPADataSource.execute(JPADataSource.java:439)
        at com.isomorphic.application.AppBase.executeDefaultDSOperation(AppBase.java:721)
        at com.isomorphic.application.AppBase.executeAppOperation(AppBase.java:658)
        at com.isomorphic.application.AppBase.execute(AppBase.java:491)
        at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:1948)
        at it.ccg.infoprovider.smartgwt.server.dmi.BuiltInDmiCmtEAO.fetch(BuiltInDmiCmtEAO.java:25)
        at it.ccg.infoprovider.smartgwt.server.dmi.EJSLocal0SLBuiltInDmiCmtEAO_b8333c0e.fetch(EJSLocal0SLBuiltInDmiCmtEAO_b8333c0e.java)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
        at java.lang.reflect.Method.invoke(Method.java:611)
        at com.isomorphic.base.Reflection.adaptArgsAndInvoke(Reflection.java:950)
        at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:386)
        at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:64)
        at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:1945)
        at com.isomorphic.servlet.IDACall.handleDSRequest(IDACall.java:199)
        at com.isomorphic.servlet.IDACall.processRPCTransaction(IDACall.java:156)
        at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:121)
        at com.isomorphic.servlet.IDACall.doPost(IDACall.java:73)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
        at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:152)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
        at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1657)
        at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1597)
        at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:131)
        at com.isomorphic.servlet.CompressionFilter.doFilter(CompressionFilter.java:259)
        at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:188)
        at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:116)
        at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:77)
        at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:908)
        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:934)
        at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:502)
        at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:179)
        at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3935)
        at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276)
        at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:931)
        at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1583)
        at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186)
        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
        at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:276)
        at com.ibm.ws.ssl.channel.impl.SSLConnectionLink.determineNextChannel(SSLConnectionLink.java:1048)
        at com.ibm.ws.ssl.channel.impl.SSLConnectionLink$MyReadCompletedCallback.complete(SSLConnectionLink.java:642)
        at com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1784)
        at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
        at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
        at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
        at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
        at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
        at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
        at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
        at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1604)




        As you can see in the first log line, the SmartGwt engine try to execute the following jpa query:
        "select _HistoricalPricesEntity, id1 from HistoricalPricesEntity _HistoricalPricesEntity left outer join _HistoricalPricesEntity.id id1"

        This is an error. It makes a join between HistoricalPricesEntity (the entity class) and _HistoricalPricesEntity.id (which is an instance of HistoricalPricesEntityPK class).


        Why this behavior?


        Thanks in advance.



        Giervella
        Last edited by giervella; 31 Aug 2012, 00:26.

        Comment


          #5
          Hi,

          JPADataSource does not support composite primery keys.

          Regards,
          Alius

          Comment


            #6
            If you can't get rid of the composite primary key in your data model, the best way around the limitation of JPADataSource is to use DMI to call JPA APIs directly.

            When returning data, declare a single primaryKey field in the DataSource and return a value for that field that is unique, for example, by (safely) concatenating the real primaryKeys.

            Comment


              #7
              Ok, but if i manually manage queries in DMI, then i have to manually manage other features such as ListGrid filter.. is it right?
              How can i do this?


              Thank you,

              Giervella

              Comment


                #8
                The criteria being sent from the client are available in the DSRequest. You would need to turn this into JPA/Hibernate Criteria objects for whatever fields where you want to support filtering, and likewise support criteria and sort directions. Example code for doing this for Hibernate is here.
                Last edited by Isomorphic; 10 Sep 2012, 10:01.

                Comment


                  #9
                  Ok.
                  But now i have the same problem of:
                  http://forums.smartclient.com/showthread.php?t=9767&highlight=grid+filter+button

                  I need to call my custom dmi logic through a custom client.DSRequest to return the correct results.

                  How can i customize the filter button behavior?


                  Thank you,


                  Giervella

                  Comment


                    #10
                    ..and i have the same problem in result ordering, when i click on ListGridField (Sort Ascending, Sort Descending).
                    How can i create and send my custom DSRequest on click?


                    Thank you,


                    Giervella

                    Comment


                      #11
                      Hi,

                      I've just committed composite primary key support for JPA data source.

                      You can test it with next nightly build.

                      Regards,
                      Alius

                      Comment


                        #12
                        There is no need to send a custom DSRequest. Clicking the filter button or clicking a grid header will result in a DSRequest that already contains correct filter and sort information being sent to the server. Simply respond with an appropriate DSResponse.

                        Comment


                          #13
                          First, thank you Alius!


                          I need to send a custom DSRequest because i need to send to the server some custom parameters.
                          In fetching data i do this in the following way:

                          DSRequest myDSRequest = new DSRequest();
                          myDSRequest.SET_CUSTOM_PARAMS();
                          ListGrid.fetchData(new Callback(), myDSRequest);

                          I need to do the same for filters and grid headers.
                          How?


                          Thank you for your help,


                          Giervella

                          Comment


                            #14
                            If you are trying to send certain fixed parameters to the server, use DataSource.transformRequest().

                            If you are trying to identify requests coming from a specific component, use listGrid.fetchOperation.

                            If you are trying to do this because you think it is needed because of your server-side custom code for JPA, this does not make sense, and we're not sure where the confusion is but you need to re-examine your basic assumptions.

                            Comment


                              #15
                              I don't try to send fixed parameters to the server.
                              I don't try to identify requests coming from a specific component.

                              I try to send a custom DSRequest only when filtering or ordering data conteined in a ListGrid, in the same way i do for CRUD operations.

                              I'd like to know if it is possible.
                              If not, i'm sure the problem are some basic assumption i've done, then i'll find SmartGwt architecture consistent ways.


                              Thank you,


                              Giervella

                              Comment

                              Working...
                              X