[ 
https://issues.apache.org/jira/browse/THRIFT-1871?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13611096#comment-13611096
 ] 

Jens Geyer commented on THRIFT-1871:
------------------------------------

Thoughts becoming longer ...

{quote}
The protocols probably can handle this, IIRC.
{quote}

Actually they probably can't, but they indeed can, if we just help them a 
little. 

Sounds confusing? Let me explain. Consider the service above:

{code}
struct User {
  1: i32 id;
  2: optional i32 born;
  3: string name;
}

exception OhMyGosh { }
 
service UserService {
  User getUserById(1: i32 id, 2: bool createOnTheFly) throws (1: OhMyGosh err);
}
{code}

With regard to the Messages being sent back and forth, we could write it 
slightly different, but still transprting the same data:

{code}
struct getUserById_args {
  1: i32 id,
  2: bool createOnTheFly
}
 
struct getUserById_result {
  1: optional User user
}
 
service UserService {
  getUserById_result getUserById(1: getUserById_args args);
}
{code}

Let's say, we not only want the user to be created on the fly, but also get 
informed about that occurrence. Additionally, we would like the createOnTheFly 
flag to be default to false on input, unless we explicitly specify value for it:

{code}
struct getUserById_args {
  1: i32 id,  
  2: bool createOnTheFly = false
}
 
struct getUserById_result {
  1: optional User user,
  2: bool userCreated
}
 
service UserService {
  getUserById_result getUserById(1: getUserById_args args) throws (1: OhMyGosh 
err);
}
{code}

Now let's transform that back into something that looks like our usual syntax:

{code}
service UserService {
  optional User getUserById(1: i32 id, 2: optional bool createOnTheFly = false) 
                   returns (1: optional bool created ) 
                   throws (1: OhMyGosh err);
}
{code}

or even

{code}
service UserService {
  void getUserById(1: i32 id, 2: optional bool createOnTheFly = false) 
                   returns (1: optional bool created; 2: optional User user) 
                   throws (1: OhMyGosh err);
}
{code}

This would not only solve the issue that the IDL accepts defaults at function 
args, but does not use them, which I recently discovered. Implementing this 
cleverly could even keep compatibility.

But what about the nullables? Well, from my feeling this is a different story 
(although a related one), because a nullable is in fact nothing more than 
syntactic sugar for _isset.

                
> Better null-safe handling
> -------------------------
>
>                 Key: THRIFT-1871
>                 URL: https://issues.apache.org/jira/browse/THRIFT-1871
>             Project: Thrift
>          Issue Type: Brainstorming
>          Components: Compiler (General)
>            Reporter: Eirik Sletteberg
>         Attachments: Add_nullable_modifier_to_functions.patch
>
>
> Optional fields are not really handled well, especially in java clients. 
> (NullPointerExceptions everywhere)
> Scrooge (Twitter's alternative Thrift compiler implementation) solves this 
> problem by wrapping all optional fields in an Option<T> class. Could this be 
> implemented in Thrift?
> As of today, services have no way of returning empty results; for example
> UserService {
>   1: User getUser(1: i32 id)
> }
> cannot return an empty user if the ID is not found.
> There are a few ways to solve this:
> UserService {
>   1: User getUser(1: i32 id) throws UserNotFoundException
> }
> -- or --
> UserService {
>   1: List<User> getUser(1: i32 id)
> }
> where an empty list is returned of no user is found, and a list containing 
> one item is returned if a user is found.
> -- or --
> UserResult {
>   1: bool exists;
>   2: User user;
> }
> UserService {
>   1: UserResult getUser(1: i32 id)
> }
> I don't like any of them.
> One could solve this by letting the "optional" keyword apply to methods:
> UserService {
>   1: optional User getUser(1: i32 id)
> }
> or adding a new type to the IDL; the Option type:
> UserService {
>   1: Option<User> getUser(1: i32 id)
> }
> and then, like Scrooge does, generate code that wraps the optional fields in 
> an "Option" type, which is null-safe.
> The Option type could also be used in structs:
> struct User {
>   1: i32 id;
>   2: string name;
>   3: optional string email;
> }
> -- or --
> struct User {
>   1: i32 id;
>   2: string name;
>   3: Option<string> email;
> }
> Either way, a null-safe Option wrapper would be used in the generated java 
> code.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to