Support nested parameter injection into beans
---------------------------------------------

                 Key: CXF-2153
                 URL: https://issues.apache.org/jira/browse/CXF-2153
             Project: CXF
          Issue Type: Improvement
          Components: REST
    Affects Versions: 2.2.1
            Reporter: Craig Muchinsky
             Fix For: 2.2.1


The current CXF extension for handling parameter injection into beans does not 
handle the case where you want to set values on beans that are within other 
beans. Take the following simple example:

class Name 
{ 
    String first; 
    String last; 
} 

class Address 
{ 
    String city; 
    String state; 
} 

class Person 
{ 
    Name legalName; 
    Address homeAddr; 
    String race; 
    String sex; 
    Date birthDate; 
} 

class MyService 
{ 
    @GET 
    @Path("/getPerson") 
    Person getPerson(@QueryParam("") Person person); 
} 

I would like to be able to pass something like: 

/getPerson?sex=M&legalName.first=John&legalName.last=Doe&homeAddr.city=Reno&homeAddr.state=NV

I will attach a patch that contains modifications to the InjectionUtils class 
to support this behavior. In addition, the patch contains some unit test 
modifications the ensure more complex recursions of nested beans are taken care 
of. Note that no JAXRS* systests were harmed in the making of this patch, they 
all passed successfully.

The only notation change to the parameter format is the addition of the '.' to 
the name, which is the trigger that tells the code to assume a nested bean. 
Since this change is isolated to the injection processing logic, the capability 
works for Query, Form, Matrix, and Path parameter types. With that said, my 
functional testing has focused on query parameters, although I did change the 
unit tests for all for types to exercise the new capability.

When dealing with nested beans and lists things get a bit more complicated. 
Since the code doesn't introduce an indexing notation, there are a few rules 
that the consumer needs to be aware of. First, you can't inject list items into 
nested beans that are contained within a list themselves. Take the following 
bean class as an example:

class RecursiveBean
{ 
    String s;
    Integer i;
    List<String> sList;
    List<RecursiveBean> bList;
}

The following would be fine:

/getBean?s=top&sList=toplist1&sList=toplist2&bList.s=nested&bList.s=nested

You would end up with 1 top level bean with s='top' containing a sList with 2 
items, and a bList with 2 nested beans both with s='nested'. The following case 
however won't work:

/getBean?s=top&sList=toplist1&sList=toplist2&bList.s=nested&bList.s=nested&bList.sList=nestedList1&bList.sList=nestedList2

The main reason it won't work is that you don't know where to inject 
'nestedList1' and 'nestedList2', do they both go to the first, or should they 
be split up between the 2 nested beans. As such, if a nested list of this type 
is encountered, the values are simply not injected at all.

The second nuance to be aware of is that nested beans contained within a list 
must have their parameters set in the correct order, and not sparsely 
populated. Using the class defined in the previous example consider the 
following query:

/getBean?bList.s=nested1&bList.i=1&bList.s=nested2&bList.i=2

This is a valid query that creates 2 nested beans within bList, the first with 
s=nested1, i=1, and the second with s=nested2, i=2. Now imagine you wanted 2 
nested beans with 'i' set the same as above, but the first not having 's' set 
at all. If you tried:

/getBean?bList.i=1&bList.s=nested2&bList.i=2

You would end up with the first bean having s=nested2 instead of being blank :(

I don't think the limitations that I mention represent common everyday use 
cases, however its worth pointing them out so folks don't hit them unexpectedly.

I hope you will consider folding this patch into the product with the next 
2.2.x release, I think it will prove to be a powerful addition to the existing 
CXF extension.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to