. . .

Own Restendpoints

By this point, you have learned how to execute methods when a new object is created, read, updated or deleted. But let's suppose you want to implement methods that are executed whenever you want, and not just when a CRUD-Method is executed. More details about the usage and implementation of the module can be found here to supplement this introduction.

Let's look at an example. Say your grocery list has become too big, and you are not sure if you can afford it anymore. So you then want to implement a method that calculates the overall price of the of the groceries in relation to your available money to see whether or not you can afford it.

But first, let's have a look at a very easy example that is already provided in every downloaded module: the ping-rest-endpoint.

The Ping Example

  1. Go to the class com.apiomat.nativemodule inside the project with your downloaded module-code.[modulename].[modulename] (Just as you did at the start of config-parameter-tutorial)

    images/download/attachments/61493779/pathToMainClass_temp.png



  2. Search for the method getSpecificRestResource . This method signifys if the module provides its own restentpoints at all. This "switch" is turned off by default. Turn it commenting the "return null" and uncommenting the line "return new RestClass(.....".

    images/download/attachments/61493779/uncommentRestResource.png
  3. Upload the module-code as always

  4. Go to the Dashboard. Now you can access a new rest-method. This rest method was implemented as a default the whole time, it just was not activated up until now. There are vairous ways in which you can access rest-endpoints of a module. The easiest way is to go to "Modules & UI > Native Modules" and search for your module entry. You have been here before in this turorial to download your module code for the first time! But now, there is a new area providing REST endpoints for this module. There is only one method available, the "A simple ping-like GET endpoint"-method. Enter the parameters, which is a name of your choice and the name of the application. Then, hit the execution button and check the response: It's the name you entered -a simple ping.

    images/download/attachments/61493779/restendpoints_1.png


    Modules & UI (1) → Native Modules (2) → Custom REST end point with parameters (3) → Send request and retrieve response (4)

  5. The second way to execute this rest-endpoint is to directly access the URL where the resource resides. In the case of your own rest-endpoints, these are located: " [base-url-of-server]/yambas/rest/modules/[moduleName]/[appName]/spec/ping/[wordYouWantThePingToReturn] ". In this example, this equals: " [base-url-of-server]/yambas/rest/modules/TutorialModule/TutorialApp/spec/ping/helloRest " . You should see the last word entered into the URL.

Now you should have a vague idea of how to use a rest-endpoint.
The question is, where did this ping-method come from in the first place?

  • Return to the project with the module-code you once downloaded. Go to the class com.apiomat.nativemodule.[modulename].RestClass

    images/download/thumbnails/61493779/goToRestclass_temp.png



  • This class contains all the rest-methods of this module. At the bottom there is the source-code for the ping-method you just used. The code-below explains the meaning of the different parts of this method through comments.

    @ApiOperation( value = "A simple ping-like GET endpoint" ) // The text on the button of the method you saw in the dashboard
     
    @GET // Indicates the type of the rest method (GET, POST, PUT, DELETE)
     
    @Path( "/ping/{param}" ) // Indicates the path to this method when calling it directly
    // through the URL. Check the url you typed in again.
    // You should see the resemblance
     
    public Response ping( @ApiParam( value = "param name" )
    @PathParam( "param" ) String param ) // The actual signature of the method.
    // The @ApiParam( value = "param name") indicates the name of this parameter
    // you saw when accessing the method through the dashboard.
    // The @PathParam( "param" ) String param - part indicates the name of the param
    // you can use inside your method...
     {
    final com.apiomat.nativemodule.Request request =
    this.getAOMRequest( ); // This call provides you with the incoming request,
    // in case you need it
     
    System.out.println( request );
     
    return Response.ok( param )
    .type( MediaType.TEXT_PLAIN ).build( ); // the return-statement. As you can see, the incoming param
    // is returned and some obligatory formatting applied.
     }

    Got it? Let's write our own rest-method!

Writing an own Rest-Endpoint

Let's remember what we are actually trying to achive: The Rest-Endpoint should recive your money as input, caluclate the overall price of the groceries currently in the database, and tell you whether or not you have enough money to shop. It's recommended to copy the ping-method as a bluepring and alter it. Here you can see the solution:

@ApiOperation(
value = "Can I go shopping with this money?",
position = 1 )
@GET
@Path( "/canIAffordIt/{theMoney}" )
public Response canIAffordIt( @ApiParam( value = "your money" ) @PathParam( "theMoney" ) String yourMoney )
{
final com.apiomat.nativemodule.Request r = this.getAOMRequest( );
 
IModel<?>[ ] groceriesInDatabase =
TutorialModule.AOM.findByNames( r.getApplicationName( ), Grocery.MODULE_NAME, Grocery.MODEL_NAME, "", r );
double sum = 0;
 
for ( IModel<?> grocery : groceriesInDatabase )
{
Grocery g = ( Grocery ) grocery;
sum += g.getPrice( );
}
 
TutorialModule.AOM.log( r.getApplicationName( ), "Current value of all groceries: " + sum );
 
Double money = Double.parseDouble( yourMoney );
if ( sum < money )
{
return Response.ok( "you have enough money !" ).type( MediaType.TEXT_PLAIN ).build( );
}
 
return Response.ok( "you don't have enough money !" ).type( MediaType.TEXT_PLAIN ).build( );
}

Most of this should be self-explanatory following the ping-example. Some additional Informations:

  • IModel<?>[ ] groceriesInDatabase = TutorialModule.AOM.findByNames( r.getApplicationName( ), Grocery.MODULE_NAME, Grocery.MODEL_NAME, "", r );

    • This mehtod queries and retrives all instances of a given class-name (aka "module-name"). This means that this method retrives all groceries currently saved in the database. The other parameters of this method, like the application-name and so on are for apiomat to localize the class you are trying to access.

    • The empty parameter of this call [ "" ] recives a query. If you wrote something like "price > 3". You already came briefly in touch with queries for databases in this tutorial. As we passed an empty query, simply all instances are returned. For further explanations concerning queries, look here.

    • This method always returns an array of all queried instances as the type "IModel<?>", which is the global parent-class from which all apiomat models stem.

  • Grocery g = ( Grocery ) grocery
    • The instances returned by the previous call currently have the type "IModel<?>", which is the global parent-class from which all apiomat models stem. You have to type-cast them to the actual type.

Now you can upload the module code again, go to the dashboard, browse through "Modules & UI" and search for your module. The new method should be there and work as intented! Also try to access this method through the URL-Method we tried out for the ping-example.

images/download/attachments/61493779/restendpoints_2.png

You now know two methods by which you can access your own Rest-Endpoint. Acutally, there is a third one, explained in the next tutorial.