简体   繁体   中英

How can I share classes between Google cloud endpoints?

I have several endpoint classes that I have exposed to my Android client. The methods in these endpoints take entity type parameters. As you know that the endpoints have been exposed through the @Api annotation, I have not annotated the entity type parameters with @Api. The problem I am facing is these endpoints share a set of entity classes but when I generate the endpoint libs, these entity types are generated for each endpoint for the same classes. I wanted to have a common set of these classes for all the endpoints. Let me give you an example to elaborate the problem:

Lets say, I have an endpoint with the annotation:

@Api(
        name = "learnerProfileVer1Api",
        version = "v1",
        resource = "learnerProfileVer1",
        namespace = @ApiNamespace(
                ownerDomain = "create.account.backend.learncity.com",
                ownerName = "create.account.backend.learncity.com",
                packagePath = ""
        )
)
public class Endpoint1{

@ApiMethod(
            name = "insert",
            path = "learnerProfileVer1",
            httpMethod = ApiMethod.HttpMethod.POST)
    public LearnerProfileVer1 insert(LearnerProfileVer1 learnerProfileVer1) {....}

}

And another endpoint,

@Api(
        name = "searchApi",
        version = "v1",
        title = "Search API",
        namespace = @ApiNamespace(
                ownerDomain = "learncity.com",
                ownerName = "Learncity",
                packagePath = ""
        )
)
public class SearchTutorsEndpoint {

@ApiMethod(name = "searchTutors",
            httpMethod = ApiMethod.HttpMethod.POST)
    public CollectionResponse<TutorProfileVer1> searchTutors(SearchTutorsQuery searchTutorsQuery, @Nullable @Named("cursor") String cursor, @Nullable @Named("limit") Integer limit) {...}

}

You can see in the above 2 endpoints that I have LearnerProfileVer1 and SearchTutorsQuery entity type parameters. These 2 classes use a few other classes that are common.

Now, when I generate the client-libs, I get 1 for learnerProfileVer1Api which has a model package in it where it has those classes and I get client-lib separately for SearchApi that has a separate model package with the SAME classes. This problem magnifies when I make link my client code to these client libs and I find 3 different versions of the same class.

Is there any solution to make these classes have a single set of client-libs generated?

There isn't any elegant solution to this problem but there is one I have found using Multiclass API. I had to redesign my backend code which broke my code on the client side but it is worth it and you realize it when the project complexity increases. Anyway, you can read about the Multiclass API here .

Here is a simple example of how you might do it.

    /**
     * An endpoint class we are exposing
     */
    @Api(
            name = "userApi",
            version = "v1",
            namespace = @ApiNamespace(
                    ownerDomain = "backend.myapplication.DJ.example.com",
                    ownerName = "backend.myapplication.DJ.example.com",
                    packagePath = ""
            )
    )
    @ApiClass(
            resource = "account"
    )
    public class AccountEndpoint {

        /**
         * A simple endpoint method that takes a name and says Hi back
         */
        @ApiMethod(name = "sayHi")
        public MyBean sayHi(@Named("name") String name) {
            MyBean response = new MyBean();
            response.setData("Hi, " + name);

            return response;
        }

    }


/**
 * Another endpoint class we are exposing
 */
@Api(
        name = "userApi",
        version = "v1",
        namespace = @ApiNamespace(
                ownerDomain = "backend.myapplication.DJ.example.com",
                ownerName = "backend.myapplication.DJ.example.com",
                packagePath = ""
        )
)
@ApiClass(
        resource = "search"
)
public class SearchEndpoint {

    private static final Logger logger = Logger.getLogger(SearchEndpoint.class.getName());

    /**
     * This method gets the <code>MyBean</code> object associated with the specified <code>id</code>.
     *
     * @param id The id of the object to be returned.
     * @return The <code>MyBean</code> associated with <code>id</code>.
     */
    @ApiMethod(name = "getMyBean")
    public MyBean getMyBean(@Named("id") Long id) {
        // TODO: Implement this function
        logger.info("Calling getMyBean method");
        return null;
    }

    /**
     * This inserts a new <code>MyBean</code> object.
     *
     * @param myBean The object to be added.
     * @return The object to be added.
     */
    @ApiMethod(name = "insertMyBean")
    public MyBean insertMyBean(MyBean myBean) {
        // TODO: Implement this function
        logger.info("Calling insertMyBean method");
        return myBean;
    }
}

Importantly, you can see here that the 2 APIs differ through the resource in @APIClass annotation.

These 2 endpoints accept account related requests and search related requests for the user . This is the logical relationship between the 2 APIs(grouped under userApi). Although it doesn't seem bad, you will end up all the endpoint methods in the same package and the API explorer which can make things to find and test a bit tedious but it is totally worth it considering the design mess you will get into otherwise. This solution becomes further tedious when you add another API which accesses at least one of the classes that the existing endpoint uses. You will be forced to include it in the existing API. If this new API had just one or two entities in common, you might get by a unsignificant design compromise on the client side by not grouping it in the same API(and dealing with these duplicated model classes as a special case on client side)

Following points should be kept in mind when using Multiclass API:

  • Since the API identity is the same for all the endpoints, the method names must have different signature.
  • See that no two different methods end up having the same REST path.
  • Name the resource, method names, API method names as logical as possible so that you can build up on these names when a newer API is grouped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM