On 09/11/2009 08:55, Paul Sandoz wrote:
> On Nov 6, 2009, at 6:23 PM, gerard davison wrote:
>>>>> 3. Response type
>>>>>
>>>>> This would be a strong argument for adding a generic parameter to
>>>>> the Response/ResponseBuilder interfaces;
>>>>
>>>> Marc and I tried and failed miserably. We could not get things to
>>>> work with type safety using the response building pattern.
>>>>
>>> Yes, I forget the exact problem no but we couldn't get it to work
>>> satisfactorily. We settled on the GenericEntity class to capture the
>>> generic type for use with Response or non-committal return types
>>> like Object. Unfortunately this only works at runtime and isn't any
>>> use for WADL generation.
>>
>> I would be interesting to understand better why it didn't work for
>> you if you have time.
>
> Oh crap... often when one experiments with a fresh mind one can find a
> solution (see end of email).
>
> The problem we were having was we could not connect the T of the
> static method on Response to the T of the Response.ResponseBuilder.
> There is a less known (well at least to me at the time) of declaring T
> right before the declaration of the static method call, for example:
>
> List<String> l = Collections.<String>emptyList();
>
> <blush/> this is all rather embarrassing...
Well the only place I have ever seen this is in Effective Java 2ed, so
like you I hadn't heard of this language feature until this year. It is
very much a language feature that gets lost down the back of the sofa. I
would guess if you asked 100 java programmers only 1 or 2 would have
heard of it.
The other solution that occurs to me and I have seen often used is to
not bind the type in the builder until it is specified see below. The
trick is to create a new instance of ResponseBuilder when we need to
bind in the type; and pass in the internal state. Until the call to
entity(...) the generic parameter T is unbound. (I have included the
GenericEntity case; but I am not sure it would be required if the
interface is properly generic).
// Generified Response
~
public class Response<T> {
static class GListString extends GenericEntity<List<String>> {
public GListString(List<String> list) {
super(list);
}
}
private final T entity;
private Response(T entity) {
this.entity = entity;
}
public T getEntity() {
return entity;
}
public static <T> ResponseBuilder<T> start() {
return new ResponseBuilder<T>("Some State");
}
public static class ResponseBuilder<T> {
private Object state;
private Type type;
private T entity;
public ResponseBuilder(Object state) {
this.state = state;
}
public ResponseBuilder(Object state, Type type, T object) {
this(state);
this.type = type;
this.entity = object;
}
public ResponseBuilder<T> header(String name, String value) {
return this;
}
public <T, K extends GenericEntity<T>> ResponseBuilder<T>
entity(K ent) {
return new ResponseBuilder<T>(state, ent.getType(),
ent.getEntity());
}
public <T> ResponseBuilder<T> entity(T ent) {
return new ResponseBuilder<T>(state, ent.getClass(), ent);
}
public Response<T> build() {
return new Response<T>(entity);
}
}
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
GListString genericList =
new GListString(list);
Response<List<String>> response = Response
.start()
.header("Content-Type", "fudge")
.entity(list)
.build();
// Using generic entity
//
Response<List<String>> genericResponse = Response
.start()
.header("Content-Type", "fudge")
.entity(genericList)
.build();
// String example
//
Response<String> stringResponse = Response
.start() // ResponseBuilder<?>
.entity("String") // ResponseBuilder<String>
.header("Content-Type", "cheese") // ResponseBuilder<String>
.build();
}
}
>
> Unfortunately it is too late to make changes to JAX-RS 1.1. I could
> add something to Jersey in the interim.
Damm, I figured as much. Do I need to raise this as an issue for this
for the next release. I guess I am going to have to wait until 2.x for
this. As to a workaround, it would be useful the WADL issue, I guess it
could as simple as a generic subtype of these classes. I guess I will
log that with the root issue which stated this discussion, hopefully I
will have this done in a few days.
Cheers,
Gerard
>
> Paul.
>
>
> public class Main {
>
> public static class Response<T> {
>
> private final T entity;
>
> private Response(T entity) {
> this.entity = entity;
> }
>
> public T getEntity() {
> return entity;
> }
>
> public static class ResponseBuilder<T> {
> private T entity;
>
> public ResponseBuilder<T> entity(T entity) {
> this.entity = entity;
> return this;
> }
>
> public Response<T> build() {
> return new Response<T>(entity);
> }
>
> static protected <T> ResponseBuilder<T> newInstance() {
> return
> RuntimeDelegate.getInstance().<T>createResponseBuilder();
> }
> }
>
> static public <T> ResponseBuilder<T> start() {
> return new ResponseBuilder<T>();
> }
>
> }
>
> public static class RuntimeDelegate {
> public static RuntimeDelegate getInstance() {
> return new RuntimeDelegate();
> }
>
> public <T> Response.ResponseBuilder<T> createResponseBuilder() {
> return new Response.ResponseBuilder<T>();
> }
> }
>
> /**
> * @param args the command line arguments
> */
> public static void main(String[] args) {
> Response<String> r =
> Response.<String>start().entity("xx").build();
>
> String e = r.getEntity();
> System.out.println(e);
> }
> }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
--
Gerard Davison | Senior Principal Software Engineer | +44 118 924 5095
Oracle JDeveloper Web Service Tooling Development
Oracle Corporation UK Ltd is a company incorporated in England & Wales.
Company Reg. No. 1782505.
Reg. office: Oracle Parkway, Thames Valley Park, Reading RG6 1RA.
Blog http://kingsfleet.blogspot.com