Servlet API

Matreshka provides server-independent implementation of Servlet API. Web-application based on this module can be executed by Spikedog application server.

See examples of applications.

Minimal application

Initialization of application

When Spikedog loads application it lookups in loaded application's library for special symbol to resolve reference to object of application's initializer tagged type. This type should support Servlet.Container_Initializers.Servlet_Container_Initializer interface. Its On_Startup subprogram will be called after successful loading and initialization of application's dependencies. Application can do additional initialization in this subprogram (connect to database, for example) or create, register and configure listeners/servlets.

To provide this symbol application must instantiate Spikedog.Generic_Application_Initializer to application's initializer tagged type and link it in application's library. When you use GNAT tools you need to add instantiated package to the list of Library_Interfaces attribute of project file.

Here is example of application initializer tagged type:

with Servlet.Container_Initializers;
with Servlet.Contexts;

package Initializers is

   type Server_Initializer is limited
     new Servlet.Container_Initializers.Servlet_Container_Initializer
       with null record;

   overriding procedure On_Startup
    (Self    : in out Server_Initializer;
     Context : in out Servlet.Contexts.Servlet_Context'Class) is null;

end Initializers;

and instantiation of Spikedog.Generic_Application_Initializer package:

with Spikedog.Generic_Application_Initializer;

with Initializers;

package Initializer is
  new Spikedog.Generic_Application_Initializer
       (Initializers.Server_Initializer);

Building application's library with GNAT

Application must be build as GNAT's standalone library. It is recommended to use project files to do this. Minimal project file will looks like:

with "matreshka_spikedog_api.gpr";

library project Application is

   for Library_Name use "MyApplication";
   for Library_Kind use "dynamic";
   for Library_Dir use ".libs";
   for Library_Interface use ("Initializer");

end Application;

It is important to list name of application initializer's instantiation package (if used), and names of all filters' and servlets' packages as library interface. This allows compiler to generate necessary elaboration code.

Prepare package to deploy application

Spikedog expects that all application's files are provided inside some directory. There are few predefined files and subdirectories and more subdirectories can be used by application to store application's resources.

Predefined subdirectories and files are

Path Kind Description
/ directory Root directory of application's resources which is available to clients and served by default servlet
/WEB-INF directory Root directory of private application's resources
/WEB-INF/web.xml file Application deployment descriptor
/WEB-INF/lib directory Root directory of application's libraries
/WEB-INF/lib/x86_64-linux directory Directory of application's library for Linux hosted on x86-64 machine

Deployment descriptor file

web.xml file in WEB-INF directory is used to define configuration of the application. As minimum it provides name of application's shared library to be loaded by Spikedog.

<?xml version='1.0'?>
<web-app xmlns='http://forge.ada-ru.org/matreshka/xml/ns/spikedogdd'>
  <library-name>MyApplication</library-name>
</web-app>

Managing of static resources

AWFC provides default implementation of servlet to manage requests for static resources - images, styles, pages and other files. It needs to be linked with application first. It is sufficient to add it to the list of library interface units in project file:

with "matreshka_spikedog_api.gpr";

library project Application is

   for Library_Name use "MyApplication";
   for Library_Kind use "dynamic";
   for Library_Dir use ".libs";
   for Library_Interface use
    ("Initializer", 
     "AWFC",
     "AWFC.Static_Resource_Servlets");

end Application;

and configured to be used as default servlet in application deployment descriptor file

<?xml version='1.0'?>
<web-app xmlns='http://forge.ada-ru.org/matreshka/xml/ns/spikedogdd'>
  <library-name>MyApplication</library-name>

  <servlet>
    <servlet-name>StaticResource</servlet-name>
    <servlet-tag>AWFC.STATIC_RESOURCE_SERVLETS.STATIC_RESOURCE_SERVLET</servlet-tag>
  </servlet>
  <servlet-mapping>
    <servlet-name>StaticResource</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

Servlets

Minimal servlet looks like:

private with League.Strings;

private with Servlet.Generic_Servlets;
private with Servlet.HTTP_Requests;
private with Servlet.HTTP_Responses;
with Servlet.HTTP_Servlets;

package My_Servlets is

   type My_Servlet is
     new Servlet.HTTP_Servlets.HTTP_Servlet with private;

private

   type My_Servlet is
     new Servlet.HTTP_Servlets.HTTP_Servlet with null record;

   overriding procedure Do_Get
    (Self     : in out My_Servlet;
     Request  : Servlet.HTTP_Requests.HTTP_Servlet_Request'Class;
     Response : in out Servlet.HTTP_Responses.HTTP_Servlet_Response'Class);
   --  Process "GET" requests

   overriding function Get_Servlet_Info
    (Self : My_Servlet) return League.Strings.Universal_String;
   --  Name of the servlet

   overriding function Instantiate
    (Parameters : not null access
       Servlet.Generic_Servlets.Instantiation_Parameters'Class)
         return My_Servlet;
   --  Creates instance of servlet

end My_Servlets;
package body My_Servlets is

   Text_Encoding : constant League.Strings.Universal_String
     := League.Strings.To_Universal_String ("utf-8");
   Text_Plain    : constant League.Strings.Universal_String
     := League.Strings.To_Universal_String ("text/plain");

   ------------
   -- Do_Get --
   ------------

   overriding procedure Do_Get
    (Self     : in out My_Servlet;
     Request  : Servlet.HTTP_Requests.HTTP_Servlet_Request'Class;
     Response : in out Servlet.HTTP_Responses.HTTP_Servlet_Response'Class) is
   begin
      Response.Set_Status (Servlet.HTTP_Responses.OK);
      Response.Set_Content_Type (Text_Plain);
      Response.Set_Character_Encoding (Text_Encoding);
      Response.Get_Output_Stream.Write
       (League.Strings.To_Universal_String ("Hello, World!"));
   end Do_Get;

   ----------------------
   -- Get_Servlet_Info --
   ----------------------

   overriding function Get_Servlet_Info
    (Self : My_Servlet) return League.Strings.Universal_String is
   begin
      return
        League.Strings.To_Universal_String ("Hello, World!");
   end Get_Servlet_Info;

   -----------------
   -- Instantiate --
   -----------------

   overriding function Instantiate
    (Parameters : not null access
       Servlet.Generic_Servlets.Instantiation_Parameters'Class)
         return My_Servlet
   is
      pragma Unreferenced (Parameters);

   begin
      return (Servlet.HTTP_Servlets.HTTP_Servlet with null record);
   end Instantiate;

end My_Servlets;

It needs to be linked with application's shared library, so add it to library interface in project file:

with "matreshka_spikedog_api.gpr";

library project Application is

   for Library_Name use "MyApplication";
   for Library_Kind use "dynamic";
   for Library_Dir use ".libs";
   for Library_Interface use
    ("Initializer", 
     "My_Servlets",
     "AWFC",
     "AWFC.Static_Resource_Servlets");

end Application;

and be instantiated in application deployment description file as well as to map '/my' path to it:

<?xml version='1.0'?>
<web-app xmlns='http://forge.ada-ru.org/matreshka/xml/ns/spikedogdd'>
  <library-name>hds_calcs</library-name>

  <servlet>
    <servlet-name>StaticResource</servlet-name>
    <servlet-tag>AWFC.STATIC_RESOURCE_SERVLETS.STATIC_RESOURCE_SERVLET</servlet-tag>
  </servlet>
  <servlet-mapping>
    <servlet-name>StaticResource</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-tag>MY_SERVLETS.MY_SERVLET</servlet-tag>
  </servlet>
  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/my</url-pattern>
  </servlet-mapping>
</web-app>
Last modified 4 weeks ago Last modified on Oct 27, 2017, 12:20:23 PM