You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Jim Talbut <jt...@spudsoft.co.uk> on 2013/12/06 20:10:40 UTC

A FIQL question

Hi,

I have a JPA entity model that has the following chain of relationships:

Order_JpaImpl {
     @OneToMany(mappedBy = "order", fetch = FetchType.EAGER, cascade = 
{CascadeType.ALL})
     List< OrderLine_JpaImpl> orderLines = new LinkedList<>();
}

OrderLine_JpaImpl {
     @ManyToOne(fetch = FetchType.EAGER)
     @JoinColumn(name = "prdId", nullable = false)
     @ForeignKey
     @Index
     private Product_JpaImpl orderLineItem;
}

Product_JpaImpl {
     @ManyToOne( cascade = {}, targetEntity = Show_JpaImpl.class, fetch 
= FetchType.EAGER )
     @JoinColumn( name="shwId", nullable = false )
     @ForeignKey
     @Index
     private Show_JpaImpl show;
}

Show_JpaImpl {
     @Column( length = 32, unique = true, nullable = false )
     private String shortName;
}

I want to use FIQL to get all the orders that include orderlines that 
have products from a given show.
So I have a simple search expression: show==AMND
And a mapping:
     private static Map<String,String> createBeanNameMap() {
         Map<String,String> map = new HashMap<>();
         map.put("customerdisplay","customerDisplay");
         map.put("ordertime","orderTime");
         map.put("fulfilmentstatus","fulfilmentStatus");
         map.put("show","orderLines.orderLineItem.show.shortName");
         return map;
     }
That is used by:
         SearchCondition<ImplType> searchCondition = 
searchContext.getCondition(targetClass, getBeanNameMap());

And that always returns null :(

I think what I'm trying to achieve is equivalent to the "all the books 
with good reviews written by Ted" example at 
http://cxf.apache.org/docs/jax-rs-search.html, but I'm getting an error 
inside the parser when it finds that orderLines is a List.

So my question is, should this work?
Is it supposed to be possible to go via a one-to-many join and return 
parents with a child that matches?

I'm using CXF 2.7.7.

Thanks.

Jim

Re: A FIQL question

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi,
On 11/12/13 15:54, Jim Talbut wrote:
> Hi Sergey,
>
> I've been using OpenJPA, but I don't mind it not working with interfaces
> as long as it is documented.
> Anyone using interfaces can do what I did, which is to have:
> public interface OrderLine
> {
>      Product getOrderLineItem();
>      void setOrderLineItem( Product orderLineItem );
> }
>
> @Entity
> public class OrderLine_JpaImpl implements OrderLine, Serializable {
>
>      @ManyToOne(fetch = FetchType.EAGER)
>      @JoinColumn(name = "prdId", nullable = false)
>      @ForeignKey
>      @Index
>      private Product_JpaImpl orderLineItem;
>
>      @Override
>      public Product_JpaImpl getOrderLineItem() {
>          return orderLineItem;
>      }
>
>      @Override
>      public void setOrderLineItem(Product orderLineItem) {
>          setOrderLineItem((Product_JpaImpl)orderLineItem);
>      }
>
>      public void setOrderLineItem(Product_JpaImpl orderLineItem) {
>          this.orderLineItem = orderLineItem;
>      }
>
> }
>
> I didn't know that Java permitted a sub class to return a sub class from
> an override (i.e. the way getOrderLineItem is considered an override
> despite returning a more specific type).
> This way the getter always returns the Entity type, and we have a hidden
> setter that accepts the correct type.
>
> I reckon that having your generic code be unable to know that it can use
> setOrderLineItem(Product orderLineItem) is a reasonable limitation.
>
> I think the problem I'm left with is caused by trying to specify
> properties of a child of a list, rather than being related to the
> interfaces.
>
Thanks for the info above, I haven't setup a JPA2 test, but I did a 
trivial fix to get interface properties supported as it may be needed 
even without JPA2. Please test it after we get CXF-5449 done

Cheers, Sergey
> Jim
>
>
>
> On 11/12/2013 13:14, Sergey Beryozkin wrote:
>> Hi Jim
>> Thanks; by the way I can't setup a test where an entity returns an
>> interface. Apparently not all JPA2 implementations support it.
>> We can do a basic interface proxy to get a template working with
>> interfaces, but I will need some help with configuring persistence.xml
>> and adding a test dependency to pom.xml,
>>
>> so, can you do it please, update persistence.xml in
>> rt/rs/extensions/search and pom.xml and send the diff to me or open a
>> JIRA (Support for testing another JPA2 implementation) ?
>>
>> Thanks, Sergey
>>
>> On 09/12/13 20:40, Jim Talbut wrote:
>>> On 09/12/2013 13:28, Sergey Beryozkin wrote:
>>>> org.apache.cxf.jaxrs.ext.search.jpa.JPATypedVisitorTest has few tests
>>>> where collections of primitive and complex types are used.
>>>>
>>>> Can you please open a JIRA and prototype the way the beans are
>>>> linked to
>>>> each other (please narrow it down to the faulty path only), somehow the
>>>> parser has got confused, needs to be fixed
>>>>
>>>> Thanks, Sergey
>>>
>>> Thanks Sergey.
>>> Created https://issues.apache.org/jira/browse/CXF-5449, mainly as a copy
>>> of this email.
>>> I /think/ the failure occurs when you have:
>>> 1. A parent entity containing a list of children.
>>> 2. The children entities contain a single grandchild.
>>> 3. The search is for a property of the grandchild.
>>> And it fails when it tries to set the grandchild in the child.
>>>
>>> I've actually got another layer in the hierarchy (great-grandchild), but
>>> given where the exception comes from I suspect that isn't needed to
>>> cause the failure.
>>>
>>> Jim
>>>
>>>
>>
>>
>

Re: A FIQL question

Posted by Jim Talbut <jt...@spudsoft.co.uk>.
Hi Sergey,

I've been using OpenJPA, but I don't mind it not working with interfaces 
as long as it is documented.
Anyone using interfaces can do what I did, which is to have:
public interface OrderLine
{
     Product getOrderLineItem();
     void setOrderLineItem( Product orderLineItem );
}

@Entity
public class OrderLine_JpaImpl implements OrderLine, Serializable {

     @ManyToOne(fetch = FetchType.EAGER)
     @JoinColumn(name = "prdId", nullable = false)
     @ForeignKey
     @Index
     private Product_JpaImpl orderLineItem;

     @Override
     public Product_JpaImpl getOrderLineItem() {
         return orderLineItem;
     }

     @Override
     public void setOrderLineItem(Product orderLineItem) {
         setOrderLineItem((Product_JpaImpl)orderLineItem);
     }

     public void setOrderLineItem(Product_JpaImpl orderLineItem) {
         this.orderLineItem = orderLineItem;
     }

}

I didn't know that Java permitted a sub class to return a sub class from 
an override (i.e. the way getOrderLineItem is considered an override 
despite returning a more specific type).
This way the getter always returns the Entity type, and we have a hidden 
setter that accepts the correct type.

I reckon that having your generic code be unable to know that it can use 
setOrderLineItem(Product orderLineItem) is a reasonable limitation.

I think the problem I'm left with is caused by trying to specify 
properties of a child of a list, rather than being related to the 
interfaces.

Jim



On 11/12/2013 13:14, Sergey Beryozkin wrote:
> Hi Jim
> Thanks; by the way I can't setup a test where an entity returns an
> interface. Apparently not all JPA2 implementations support it.
> We can do a basic interface proxy to get a template working with
> interfaces, but I will need some help with configuring persistence.xml
> and adding a test dependency to pom.xml,
>
> so, can you do it please, update persistence.xml in
> rt/rs/extensions/search and pom.xml and send the diff to me or open a
> JIRA (Support for testing another JPA2 implementation) ?
>
> Thanks, Sergey
>
> On 09/12/13 20:40, Jim Talbut wrote:
>> On 09/12/2013 13:28, Sergey Beryozkin wrote:
>>> org.apache.cxf.jaxrs.ext.search.jpa.JPATypedVisitorTest has few tests
>>> where collections of primitive and complex types are used.
>>>
>>> Can you please open a JIRA and prototype the way the beans are linked to
>>> each other (please narrow it down to the faulty path only), somehow the
>>> parser has got confused, needs to be fixed
>>>
>>> Thanks, Sergey
>>
>> Thanks Sergey.
>> Created https://issues.apache.org/jira/browse/CXF-5449, mainly as a copy
>> of this email.
>> I /think/ the failure occurs when you have:
>> 1. A parent entity containing a list of children.
>> 2. The children entities contain a single grandchild.
>> 3. The search is for a property of the grandchild.
>> And it fails when it tries to set the grandchild in the child.
>>
>> I've actually got another layer in the hierarchy (great-grandchild), but
>> given where the exception comes from I suspect that isn't needed to
>> cause the failure.
>>
>> Jim
>>
>>
>
>


Re: A FIQL question

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Jim
Thanks; by the way I can't setup a test where an entity returns an 
interface. Apparently not all JPA2 implementations support it.
We can do a basic interface proxy to get a template working with 
interfaces, but I will need some help with configuring persistence.xml 
and adding a test dependency to pom.xml,

so, can you do it please, update persistence.xml in 
rt/rs/extensions/search and pom.xml and send the diff to me or open a 
JIRA (Support for testing another JPA2 implementation) ?

Thanks, Sergey

On 09/12/13 20:40, Jim Talbut wrote:
> On 09/12/2013 13:28, Sergey Beryozkin wrote:
>> org.apache.cxf.jaxrs.ext.search.jpa.JPATypedVisitorTest has few tests
>> where collections of primitive and complex types are used.
>>
>> Can you please open a JIRA and prototype the way the beans are linked to
>> each other (please narrow it down to the faulty path only), somehow the
>> parser has got confused, needs to be fixed
>>
>> Thanks, Sergey
>
> Thanks Sergey.
> Created https://issues.apache.org/jira/browse/CXF-5449, mainly as a copy
> of this email.
> I /think/ the failure occurs when you have:
> 1. A parent entity containing a list of children.
> 2. The children entities contain a single grandchild.
> 3. The search is for a property of the grandchild.
> And it fails when it tries to set the grandchild in the child.
>
> I've actually got another layer in the hierarchy (great-grandchild), but
> given where the exception comes from I suspect that isn't needed to
> cause the failure.
>
> Jim
>
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: A FIQL question

Posted by Jim Talbut <jt...@spudsoft.co.uk>.
On 09/12/2013 13:28, Sergey Beryozkin wrote:
> org.apache.cxf.jaxrs.ext.search.jpa.JPATypedVisitorTest has few tests
> where collections of primitive and complex types are used.
>
> Can you please open a JIRA and prototype the way the beans are linked to
> each other (please narrow it down to the faulty path only), somehow the
> parser has got confused, needs to be fixed
>
> Thanks, Sergey

Thanks Sergey.
Created https://issues.apache.org/jira/browse/CXF-5449, mainly as a copy 
of this email.
I /think/ the failure occurs when you have:
1. A parent entity containing a list of children.
2. The children entities contain a single grandchild.
3. The search is for a property of the grandchild.
And it fails when it tries to set the grandchild in the child.

I've actually got another layer in the hierarchy (great-grandchild), but 
given where the exception comes from I suspect that isn't needed to 
cause the failure.

Jim



Re: A FIQL question

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 07/12/13 12:19, Jim Talbut wrote:
> I think I've taken this as far as it will go.
> By changing all the getters to return implementation classes rather than
> interfaces, and then adding non-interface setters that take
> implementation classes I am able to get a lot further, but then I hit this:
>
> Caused by: java.lang.IllegalArgumentException: argument type mismatch;
> setter parameter type: java.util.List, set value type:
> uk.co.spudsoft.spiderweborders.model.jpaimpl.OrderLine_JpaImpl
>      at
> org.apache.cxf.jaxrs.ext.search.Beanspector.setValue(Beanspector.java:152)
> ~[cxf-rt-rs-extension-search-2.7.8.jar:2.7.8]
>      at
> org.apache.cxf.jaxrs.ext.search.Beanspector.setValue(Beanspector.java:131)
> ~[cxf-rt-rs-extension-search-2.7.8.jar:2.7.8]
>      at
> org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser$Comparison.createTemplate(FiqlParser.java:600)
> ~[cxf-rt-rs-extension-search-2.7.8.jar:2.7.8]
>
>
> OrderLines is a list of OrderLine objects, but the template is being
> created with just one and the setter doesn't know how to handle lists.
> I tried adding a setter that takes a single OrderLine, but something got
> upset when it saw that the getter and setter were of different types.
>
> Unless there is special handling for lists of strings (or primitives) I
> can't see how the example can work either.
>
org.apache.cxf.jaxrs.ext.search.jpa.JPATypedVisitorTest has few tests 
where collections of primitive and complex types are used.

Can you please open a JIRA and prototype the way the beans are linked to 
each other (please narrow it down to the faulty path only), somehow the 
parser has got confused, needs to be fixed

Thanks, Sergey

> Jim
>
> On 07/12/2013 07:59, Jim Talbut wrote:
>> Hmm, I think I've made some progress.
>> The problem seems to be caused by this:
>>
>> Order_JpaImpl {
>>      @Override
>>      public List<? extends OrderLine> getOrderLines() {
>>          return orderLines;
>>      }
>> }
>>
>> Everything public is an interface, and the reflection in the FiqlParser
>> is just using the method signatures.
>> Which ends up with it trying to instantiate an interface.
>>
>> Not sure if there is a way around this.
>> One possibility is adding a method that returns the actual datatype, but
>> that isn't visible on the interface.
>> Given that the map from external name ('show') is hidden the method that
>> it uses doesn't actually have to be visible.
>>
>> Jim
>>
>> On 06/12/2013 19:10, Jim Talbut wrote:
>>> Hi,
>>>
>>> I have a JPA entity model that has the following chain of relationships:
>>>
>>> Order_JpaImpl {
>>>      @OneToMany(mappedBy = "order", fetch = FetchType.EAGER, cascade =
>>> {CascadeType.ALL})
>>>      List< OrderLine_JpaImpl> orderLines = new LinkedList<>();
>>> }
>>>
>>> OrderLine_JpaImpl {
>>>      @ManyToOne(fetch = FetchType.EAGER)
>>>      @JoinColumn(name = "prdId", nullable = false)
>>>      @ForeignKey
>>>      @Index
>>>      private Product_JpaImpl orderLineItem;
>>> }
>>>
>>> Product_JpaImpl {
>>>      @ManyToOne( cascade = {}, targetEntity = Show_JpaImpl.class, fetch
>>> = FetchType.EAGER )
>>>      @JoinColumn( name="shwId", nullable = false )
>>>      @ForeignKey
>>>      @Index
>>>      private Show_JpaImpl show;
>>> }
>>>
>>> Show_JpaImpl {
>>>      @Column( length = 32, unique = true, nullable = false )
>>>      private String shortName;
>>> }
>>>
>>> I want to use FIQL to get all the orders that include orderlines that
>>> have products from a given show.
>>> So I have a simple search expression: show==AMND
>>> And a mapping:
>>>      private static Map<String,String> createBeanNameMap() {
>>>          Map<String,String> map = new HashMap<>();
>>>          map.put("customerdisplay","customerDisplay");
>>>          map.put("ordertime","orderTime");
>>>          map.put("fulfilmentstatus","fulfilmentStatus");
>>>          map.put("show","orderLines.orderLineItem.show.shortName");
>>>          return map;
>>>      }
>>> That is used by:
>>>          SearchCondition<ImplType> searchCondition =
>>> searchContext.getCondition(targetClass, getBeanNameMap());
>>>
>>> And that always returns null :(
>>>
>>> I think what I'm trying to achieve is equivalent to the "all the books
>>> with good reviews written by Ted" example at
>>> http://cxf.apache.org/docs/jax-rs-search.html, but I'm getting an error
>>> inside the parser when it finds that orderLines is a List.
>>>
>>> So my question is, should this work?
>>> Is it supposed to be possible to go via a one-to-many join and return
>>> parents with a child that matches?
>>>
>>> I'm using CXF 2.7.7.
>>>
>>> Thanks.
>>>
>>> Jim
>>
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: A FIQL question

Posted by Jim Talbut <jt...@spudsoft.co.uk>.
I think I've taken this as far as it will go.
By changing all the getters to return implementation classes rather than 
interfaces, and then adding non-interface setters that take 
implementation classes I am able to get a lot further, but then I hit this:

Caused by: java.lang.IllegalArgumentException: argument type mismatch; 
setter parameter type: java.util.List, set value type: 
uk.co.spudsoft.spiderweborders.model.jpaimpl.OrderLine_JpaImpl
	at 
org.apache.cxf.jaxrs.ext.search.Beanspector.setValue(Beanspector.java:152) 
~[cxf-rt-rs-extension-search-2.7.8.jar:2.7.8]
	at 
org.apache.cxf.jaxrs.ext.search.Beanspector.setValue(Beanspector.java:131) 
~[cxf-rt-rs-extension-search-2.7.8.jar:2.7.8]
	at 
org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser$Comparison.createTemplate(FiqlParser.java:600) 
~[cxf-rt-rs-extension-search-2.7.8.jar:2.7.8]


OrderLines is a list of OrderLine objects, but the template is being 
created with just one and the setter doesn't know how to handle lists.
I tried adding a setter that takes a single OrderLine, but something got 
upset when it saw that the getter and setter were of different types.

Unless there is special handling for lists of strings (or primitives) I 
can't see how the example can work either.

Jim

On 07/12/2013 07:59, Jim Talbut wrote:
> Hmm, I think I've made some progress.
> The problem seems to be caused by this:
>
> Order_JpaImpl {
>      @Override
>      public List<? extends OrderLine> getOrderLines() {
>          return orderLines;
>      }
> }
>
> Everything public is an interface, and the reflection in the FiqlParser
> is just using the method signatures.
> Which ends up with it trying to instantiate an interface.
>
> Not sure if there is a way around this.
> One possibility is adding a method that returns the actual datatype, but
> that isn't visible on the interface.
> Given that the map from external name ('show') is hidden the method that
> it uses doesn't actually have to be visible.
>
> Jim
>
> On 06/12/2013 19:10, Jim Talbut wrote:
>> Hi,
>>
>> I have a JPA entity model that has the following chain of relationships:
>>
>> Order_JpaImpl {
>>      @OneToMany(mappedBy = "order", fetch = FetchType.EAGER, cascade =
>> {CascadeType.ALL})
>>      List< OrderLine_JpaImpl> orderLines = new LinkedList<>();
>> }
>>
>> OrderLine_JpaImpl {
>>      @ManyToOne(fetch = FetchType.EAGER)
>>      @JoinColumn(name = "prdId", nullable = false)
>>      @ForeignKey
>>      @Index
>>      private Product_JpaImpl orderLineItem;
>> }
>>
>> Product_JpaImpl {
>>      @ManyToOne( cascade = {}, targetEntity = Show_JpaImpl.class, fetch
>> = FetchType.EAGER )
>>      @JoinColumn( name="shwId", nullable = false )
>>      @ForeignKey
>>      @Index
>>      private Show_JpaImpl show;
>> }
>>
>> Show_JpaImpl {
>>      @Column( length = 32, unique = true, nullable = false )
>>      private String shortName;
>> }
>>
>> I want to use FIQL to get all the orders that include orderlines that
>> have products from a given show.
>> So I have a simple search expression: show==AMND
>> And a mapping:
>>      private static Map<String,String> createBeanNameMap() {
>>          Map<String,String> map = new HashMap<>();
>>          map.put("customerdisplay","customerDisplay");
>>          map.put("ordertime","orderTime");
>>          map.put("fulfilmentstatus","fulfilmentStatus");
>>          map.put("show","orderLines.orderLineItem.show.shortName");
>>          return map;
>>      }
>> That is used by:
>>          SearchCondition<ImplType> searchCondition =
>> searchContext.getCondition(targetClass, getBeanNameMap());
>>
>> And that always returns null :(
>>
>> I think what I'm trying to achieve is equivalent to the "all the books
>> with good reviews written by Ted" example at
>> http://cxf.apache.org/docs/jax-rs-search.html, but I'm getting an error
>> inside the parser when it finds that orderLines is a List.
>>
>> So my question is, should this work?
>> Is it supposed to be possible to go via a one-to-many join and return
>> parents with a child that matches?
>>
>> I'm using CXF 2.7.7.
>>
>> Thanks.
>>
>> Jim
>


Re: A FIQL question

Posted by Jim Talbut <jt...@spudsoft.co.uk>.
Hmm, I think I've made some progress.
The problem seems to be caused by this:

Order_JpaImpl {
     @Override
     public List<? extends OrderLine> getOrderLines() {
         return orderLines;
     }
}

Everything public is an interface, and the reflection in the FiqlParser 
is just using the method signatures.
Which ends up with it trying to instantiate an interface.

Not sure if there is a way around this.
One possibility is adding a method that returns the actual datatype, but 
that isn't visible on the interface.
Given that the map from external name ('show') is hidden the method that 
it uses doesn't actually have to be visible.

Jim

On 06/12/2013 19:10, Jim Talbut wrote:
> Hi,
>
> I have a JPA entity model that has the following chain of relationships:
>
> Order_JpaImpl {
>      @OneToMany(mappedBy = "order", fetch = FetchType.EAGER, cascade =
> {CascadeType.ALL})
>      List< OrderLine_JpaImpl> orderLines = new LinkedList<>();
> }
>
> OrderLine_JpaImpl {
>      @ManyToOne(fetch = FetchType.EAGER)
>      @JoinColumn(name = "prdId", nullable = false)
>      @ForeignKey
>      @Index
>      private Product_JpaImpl orderLineItem;
> }
>
> Product_JpaImpl {
>      @ManyToOne( cascade = {}, targetEntity = Show_JpaImpl.class, fetch
> = FetchType.EAGER )
>      @JoinColumn( name="shwId", nullable = false )
>      @ForeignKey
>      @Index
>      private Show_JpaImpl show;
> }
>
> Show_JpaImpl {
>      @Column( length = 32, unique = true, nullable = false )
>      private String shortName;
> }
>
> I want to use FIQL to get all the orders that include orderlines that
> have products from a given show.
> So I have a simple search expression: show==AMND
> And a mapping:
>      private static Map<String,String> createBeanNameMap() {
>          Map<String,String> map = new HashMap<>();
>          map.put("customerdisplay","customerDisplay");
>          map.put("ordertime","orderTime");
>          map.put("fulfilmentstatus","fulfilmentStatus");
>          map.put("show","orderLines.orderLineItem.show.shortName");
>          return map;
>      }
> That is used by:
>          SearchCondition<ImplType> searchCondition =
> searchContext.getCondition(targetClass, getBeanNameMap());
>
> And that always returns null :(
>
> I think what I'm trying to achieve is equivalent to the "all the books
> with good reviews written by Ted" example at
> http://cxf.apache.org/docs/jax-rs-search.html, but I'm getting an error
> inside the parser when it finds that orderLines is a List.
>
> So my question is, should this work?
> Is it supposed to be possible to go via a one-to-many join and return
> parents with a child that matches?
>
> I'm using CXF 2.7.7.
>
> Thanks.
>
> Jim