Difference between revisions of "SmartGears"

From Gcube Wiki
Jump to: navigation, search
(Software-as-Resource)
(Container Descriptor)
 
(48 intermediate revisions by 5 users not shown)
Line 4: Line 4:
 
<code>SmartGears</code> is a set of Java libraries that turn <code>Servlet</code>-based containers and applications into <code>gCube</code> resources, ''transparently''.
 
<code>SmartGears</code> is a set of Java libraries that turn <code>Servlet</code>-based containers and applications into <code>gCube</code> resources, ''transparently''.
  
In this document, we motivate <code>SmartGears</code> and explain how it improves over existing <code>gCube</code> solutions. The discussion is relevant to node and infrastructure managers, who perform and maintain <code>Smartgears</code> installations, and to developers, who package or write software for a <code>gCube</code>  infrastructure.
+
In this document, we motivate <code>SmartGears</code> and explain how it improves over existing <code>gCube</code> solutions. The discussion is relevant to node and infrastructure managers, who perform and maintain <code>Smartgears</code> installations, and to developers, who package or write software for a <code>gCube</code>  infrastructure.
  
 
= Rationale =
 
= Rationale =
Line 41: Line 41:
 
Traditionally, enabling <code>SaR</code> and <code>CaR</code> has been the main value proposition of the <code>gCube Core Framework</code> (<code>gCF</code>). The way <code>gCF</code> delivers that value has limitations, however:
 
Traditionally, enabling <code>SaR</code> and <code>CaR</code> has been the main value proposition of the <code>gCube Core Framework</code> (<code>gCF</code>). The way <code>gCF</code> delivers that value has limitations, however:
  
* <code>gCF</code> is a framework to ''develop'' <code>SaR</code>: its class hierarchies, interfaces, callbacks, and helper objects guide and simplify the task of writing software that directly meets our management requirements. Simply put, <code>gCF</code> lets us develop <code>SaR</code> specifically and exclusively for <code>gCube</code>. This "closed-world" assumption is not a bad thing insofar as all the <code>SaR</code> we need is part of <code>gCube itself</code>. Indeed, <code>gCF</code> has helped us a great deal to grow <code>gCube</code> consistently. However, it does becomes a problem when we want to:
+
* <code>gCF</code> is a framework to ''develop'' <code>SaR</code>: its class hierarchies, interfaces, callbacks, and helper objects guide and simplify the task of writing software that directly meets our management requirements. Simply put, <code>gCF</code> lets us develop <code>SaR</code> specifically and exclusively for <code>gCube</code>. This "closed-world" assumption is not a bad thing insofar as all the <code>SaR</code> we need is part of <code>gCube</code> itself. Indeed, <code>gCF</code> has helped us a great deal to grow <code>gCube</code> consistently. However, it does becomes a problem when we want to:
  
*: reuse <code>gCube</code> software externally to the infrastructure;
+
:* reuse <code>gCube</code> software externally to the infrastructure;
*: bring existing software into the infrastructure;
+
:* bring existing software into the infrastructure;
*: encourage third parties to develop software for the infrastructure.  
+
:* encourage third parties to develop software for the infrastructure.  
  
:: It also becomes a problem if we wish to deviate from the type of <code>SaR</code> that we can develop with <code>gCF</code>, which brings us to the next point:
+
: It also becomes a problem if we wish to deviate from the type of <code>SaR</code> that we can develop with <code>gCF</code>, which brings us to the next point:
  
 
* with <code>gCF</code>, the only <code>CaR</code> we get is the <code>Globus</code> container, and the only type of <code>SaR</code> we can enable are<code> JAX-RPC</code> services that run in that container.  We cannot:
 
* with <code>gCF</code>, the only <code>CaR</code> we get is the <code>Globus</code> container, and the only type of <code>SaR</code> we can enable are<code> JAX-RPC</code> services that run in that container.  We cannot:
  
*:  develop <code>SaR</code> as a <code>Rest</code> service, or as a plain <code>Web Application</code>;
+
:* develop <code>SaR</code> as a <code>Rest</code> service, or as a plain <code>Web Application</code>;
*: develop  <code>SaR</code> using modern standards for <code>Soap</code> services (e.g. <code>JAX-WS</code>);  
+
:* develop  <code>SaR</code> using modern standards for <code>Soap</code> services (e.g. <code>JAX-WS</code>);  
*: run <code>SaR</code> in popular, modern, and performant application containers (e.g. <code>Tomcat</code>, <code>Jetty</code>, full-blown <code>JEE</code> servers).  
+
:* run <code>SaR</code> in popular, modern, and performant application containers (e.g. <code>Tomcat</code>, <code>Jetty</code>, full-blown <code>JEE</code> servers).  
  
 
:: Overall, we are severely limited in our choice of development stack. This creates an evolution problem for <code>gCube</code>, as well as an obstacle to its adoption and further growth.
 
:: Overall, we are severely limited in our choice of development stack. This creates an evolution problem for <code>gCube</code>, as well as an obstacle to its adoption and further growth.
Line 60: Line 60:
  
 
Overall, there are at least two themes in the issues above:
 
Overall, there are at least two themes in the issues above:
 +
 
* ''age'': <code>gCF</code>, <code>Globus</code>, and their technological context are well dated by now;
 
* ''age'': <code>gCF</code>, <code>Globus</code>, and their technological context are well dated by now;
* ''visibility'': <code>gCF</code> sits right at the top of the software’s stack and right in the middle of its design.  
+
* ''visibility'': <code>gCF</code> sits right at the top of the software’s stack and right in the middle of its design.
  
 
==Less is More ==
 
==Less is More ==
  
If we look at gCF as an ageing solution, the temptation is to revamp and expand: align with new standards for Soap services, open up to Rest services, and perhaps move towards modern containers. The is substantial work, however, and it would have a dramatic impact on gCube. It would also be short-sighted work, as a cycle of five years may well bring us back where we are now.  
+
If we look at <code>gCF</code> as an ageing solution, the temptation is to revamp and expand: align with new standards for <code>Soap</code> services, open up to <code>Rest</code> services, and perhaps move towards modern containers. The is substantial work, however, and it would have a dramatic impact on <code>gCube</code>. It would also be short-sighted work, as a cycle of five years may well bring us back where we are now.
We believe instead that visibility is the key problem to address: if gCF weren’t visible to begin with, its age would be of little of no concern. With Smartgears we propose the same net value as gCF, but deliver it in a completely different fashion: we move away from frameworks and make Smartgears invisible to the software, not part of its stack at all. As a result, gCube is invisible too and any software can run in the infrastructure: SaR becomes a nature that software acquires at runtime;
+
Indeed, Smartgears has little requirements to raise against the software. As we shall see, all we ask of software is to be based on the Servlet specifications, which define the hooks that we need to track its lifecycle and its use. The software is thus a Web Application and may more specifically be a Soap service, a Rest service, or a generic Web Application. It may adopt different standards and technologies (e.g. JAX-RPC, JAX-WS, JAX-RS, but also DI technologies, persistence technologies, etc.). And of course it may run in any container that is Servlet-compliant (Web Containers, Application Servers)..
+
We believe instead that visibility is the key problem to address: if <code>gCF</code> weren’t visible to begin with, its age would be of little of no concern. With <code>Smartgears</code> we propose the same net value as <code>gCF</code>, but deliver it in a completely different fashion: we move away from frameworks and make <code>Smartgears</code> invisible to the software, not part of its stack at all. As a result, <code>gCube</code> is invisible too and any software can run in the infrastructure: <code>SaR</code> becomes a nature that software acquires at runtime;
Finally, the evolution of Smartgears is inconsequential for the software:: most of the APIs of Smartgears remain private to Smartgears.
+
 
 +
Indeed, <code>Smartgears</code> has little requirements to raise against the software. As we shall see, all we ask of software is to be based on the <code>Servlet</code> specifications, which define the hooks that we need to track its lifecycle and its use. The software is thus a <code>Web Application</code> and may more specifically be a <code>Soap</code> service, a <code>Rest</code> service, or a generic <code>Web Application</code>. It may adopt different standards and technologies (e.g. <code>JAX-RPC</code>, <code>JAX-WS</code>, <code>JAX-RS</code>, but also <code>Dependency Injection</code> technologies, persistence technologies, etc.). And of course it may run in any container that is <code>Servlet</code>-compliant (Web Containers, Application Servers).
 +
 
 +
Finally, the evolution of <code>Smartgears</code> is inconsequential for the software: most of the APIs of <code>Smartgears</code> remain private to <code>Smartgears</code>.
  
 
== Featherweight Relations ==
 
== Featherweight Relations ==
  
Smartgears and the FeatherWeight Stack (FWS) are both solutions based on “microlibs”, and in fact share a number of them..
+
<code>Smartgears</code> and the [[Featherweight_Stack|FeatherWeight Stack]] (<code>FWS</code>) are both solutions based on ''microlibs'', and in fact share a number of them.
Smartgears is the logical counterpart of the FWS: if the first turns Java software into gCube resources, the second enables other Java software to call such resources. Together, Smartgears and the FWS provide a logical replacement of gCF and gCore.  
+
The FWS is a stack, however, i.e. a direct or indirect dependency of clients. In contrast, Smartgears live in the runtime of software but it does not need to be a compile or runtime dependency for it (but see gCube-aware applications)..  
+
<code>Smartgears</code> is the logical counterpart of the <code>FWS</code>: if the first turns Java software into <code>gCube</code> resources, the second enables other Java software to call such resources. Together, <code>Smartgears</code> and the <code>FWS</code> provide a logical replacement of <code>gCF</code> and <code>gCore</code>.
 +
 +
The <code>FWS</code> is a stack, however, i.e. a direct or indirect dependency of clients. In contrast, <code>Smartgears</code> live in the runtime of software but it does not need to be a compile or runtime dependency for it (but see [[#gCube-Aware Applications|gCube-aware applications]]).
  
 
= Requirements =
 
= Requirements =
Containers and applications need a minimal set of requirements before SmartGears can turn them into gCube resources:
+
 
containers must comply with version 3 of the Servlet specifications;
+
Containers and applications need a minimal set of requirements before <code>SmartGears</code> can turn them into <code>gCube</code> resources:
applications must include at least one gcube-app.xml configuration file alongside their deployment descriptor (i.e.. under /WEB-INF);
+
 
 +
* containers must comply with version 3 of the <code>Servlet</code> specifications;
 +
* applications must include at least one <code>gcube-app.xml</code> configuration file alongside their deployment descriptor (i.e.. under <code>/WEB-INF</code>);
 +
 
 
In addition:
 
In addition:
node managers must define a GHN_HOME environment variable that resolves to a location where SmartGears can find a container.xml configuration file;.
+
 
Starting from version 3, the Servlet specifications allow SmartGears to intercept relevant events in the lifecycle of individual applications whilst being shared across all applications, in line with the deployment scheme of SmartGears discussed below.  
+
* node managers must define a <code>GHN_HOME</code> environment variable that resolves to a location where <code>SmartGears</code> can find a <code>container.xml</code> configuration file;.
In particular, the specifications introduce a ServletContextInitializer interface that SmartGears implements to be notified of application startup. The specifications also allow programmatic registration of filters and servlets, which SmartGears uses to transparently manage applications without the need of additional configuration in their web.xml descriptor.
+
 
Configuration is thus limited to WEB-INF/gcube-app.xml and $GHN_HOME/container.xml, which provide the configuration of, respectively, the application and the container as gCube resources. We discuss their contents in the Appendices.
+
Starting from version 3, the <code>Servlet</code> specifications allow <code>SmartGears</code> to intercept relevant events in the lifecycle of individual applications whilst being shared across all applications, in line with the [[#Deployment Scheme|deployment scheme]] of <code>SmartGears</code>. In particular, the specifications introduce a <code>ServletContextInitializer</code> interface that <code>SmartGears</code> implements to be notified of application startup. The specifications also allow programmatic registration of filters and servlets, which <code>SmartGears</code> uses to transparently manage applications without the need of additional configuration in their <code>web.xml</code> descriptor.
 +
 
 +
Configuration is thus limited to <code>WEB-INF/gcube-app.xml</code> and <code>$GHN_HOME/container.xml</code>, which provide the configuration of, respectively, the application and the container as <code>gCube</code> resources. We discuss their contents in the [[#Appendices|Appendices]].
  
 
=Distribution=
 
=Distribution=
Smartgears is distributed as a tarball that contains the libraries, scripts, and configuration files required to install Smartgears in a given container, and to maintain the installation over time. Instructions on how to download, install and maintain Smartgears are available in the gCube Administration Guide and we do not duplicate them here.  
+
 
Components
+
<code>Smartgears</code> is distributed as a tarball that contains the libraries, scripts, and configuration files required to install <code>Smartgears</code> in a given container, and to maintain the installation over time. Instructions on how to download, install and maintain <code>Smartgears</code> are available in the [[SmartGears_Web_Hosting_Node_(wHN)_Installation]] and we do not duplicate them here.  
The libraries that comprise Smartgears and are bundled in its distribution are also available in our Maven repository, like any other gCube component. They can thus be resolved as Maven dependencies whenever applications need to introspect on their configuration and status as gCube resources. We discuss below this class of gCube-aware applications.
+
 
The vast majority of Smartgears libraries are “microlibs”, i.e. Java libraries with:
+
== Components ==
a narrow functional focus, i.e. provide one and only one type of functionality;
+
 
contained dependencies, i.e. depend only on other micribs and the JDK.  
+
The libraries that comprise <code>Smartgears</code> and are bundled in its distribution are also available in our [http://maven.research-infrastructures.eu/nexus/index.html <code>Maven</code> repository], like any other <code>gCube</code> component. They can thus be resolved as <code>Maven</code> dependencies whenever applications need to introspect on their configuration and status as <code>gCube resources</code>. We discuss below this class of [[#gCube-Aware Applications|<code>gCube</code>-aware applications]].
 +
 
 +
The vast majority of <code>Smartgears</code> libraries are “microlibs”, i.e. Java libraries with:
 +
 
 +
* a narrow functional focus, i.e. provide one and only one type of functionality;
 +
* contained dependencies, i.e. depend only on other microlibs and the JDK.  
 +
 
 
Using microlibs reflects a commitment to provide support which is:
 
Using microlibs reflects a commitment to provide support which is:
modular: client assemble microlibs to obtain no more and no less than the functionality they need. This avoids the spurious dependencies that are often introduced by multi-function libraries, hence limits the impact of evolving individual libraries;  
+
 
unintrusive: clients do not inherit from microlibs runtime dependencies on common, general-purpose third-party libraries. This limits the risk that such dependencies may clash with versions already available in their runtimes;   
+
* ''modular'': client assemble microlibs to obtain no more and no less than the functionality they need. This avoids the spurious dependencies that are often introduced by multi-function libraries, hence limits the impact of evolving individual libraries;  
lightweight: as an implication of modular and non-intrusive support, microlibs do not inflate the size of client runtimes.
+
 
SmartGears includes the following microlibs::
+
* ''unobtrusive'': clients do not inherit from microlibs runtime dependencies on common, general-purpose third-party libraries. This limits the risk that such dependencies may clash with versions already available in their runtimes;   
org.gcube.core:common-smartgears: the main library in SmartGears, contains all the components that provide the management logic required to turn applications and containers into gCube resources. All the other libraries are direct or indirect dependencies of common-smartgears;
+
 
org.gcube.core:common-events: a general-purpose, annotation-based eventing library used by the components in common-smartgears to sync with each other actions in a loosely-coupled manner;
+
* ''lightweight'': as an implication of modular and non-intrusive support, microlibs do not inflate the size of client runtimes.
org.gcube.core:common-validator: a general-purpose, annotation-based library for object state validation used in common-smartgears to validate configuration holding objects;
+
 
org.gcube.core:common-scope: a library with facilities related to gCube scope management;
+
<code>SmartGears</code> includes the following microlibs:
org.gcube.resources:common-gcore-resources: a library with the object bindings for the gCube resource model used in SmartGears to model application and container resource profiles ;
+
 
org.gcube.resources:registry-publisher: a client library for the gCube Registry service used in SmartGears to publish application and container profiles;
+
* <code>org.gcube.core:common-smartgears</code>: the main library in <code>SmartGears</code>, contains all the components that provide the management logic required to turn applications and containers into <code>gCube</code> resources. All the other libraries are direct or indirect dependencies of <code>common-smartgears</code>;
org.gcube.core:common-smartgears-app: a library that provides mechanisms to expose selected APIs in SmartGears to gCube-aware applications;
+
 
The distribution of SmartGears includes of course the transitive closure of the libraries above. It also includes the only 3rd party dependencies of SmartGears, namely Slf4j and Logback, which we discuss below in regard to logging.
+
* <code>org.gcube.core:common-events</code>: a general-purpose, annotation-based eventing library used by the components in <code>common-smartgears</code> to sync with each other actions in a loosely-coupled manner;
 +
 
 +
* <code>org.gcube.core:common-validator</code>: a general-purpose, annotation-based library for object state validation used in <code>common-smartgears</code> to validate configuration objects;
 +
 
 +
* <code>org.gcube.core:common-scope</code>: a library with facilities related to <code>gCube</code> scope management;
 +
 
 +
* <code>org.gcube.resources:common-gcore-resources</code>: a library with the object bindings for the <code>gCube</code> resource model used in <code>SmartGears</code> to model application and container resource profiles ;
 +
 
 +
* <code>org.gcube.resources:registry-publisher</code>: a client library for the <code>gCube Registry</code> service used in <code>common-smartgears</code> to publish application and container profiles;
 +
 
 +
* <code>org.gcube.core:common-smartgears-app</code>: a library that provides mechanisms to expose selected APIs in <code>common-smartgears</code> to [[#gCube-Aware Applications|gCube-aware applications]];
 +
 
 +
The distribution of <code>SmartGears</code> includes of course the transitive closure of the libraries above. It also includes the only 3rd party dependencies of <code>SmartGears</code>, namely <code>Slf4j</code> and <code>Logback</code>, which we discuss below in regard to [[#Logging|logging]].
  
 
= Deployment Scheme =
 
= Deployment Scheme =
The installation scripts included in the SmartGears distribution copy the SmartGears libraries in container-specific locations, where they are available to all the applications that run in the container.  
+
 
This shared deployment scheme for SmartGears is largely dictated by the need to share state about the container across applications, which remain otherwise isolated in the classloader hierarchies defined by the container. A shared installation achieves that in a container-independent manner.
+
The installation scripts included in the <code>SmartGears</code> distribution copy the <code>SmartGears</code> libraries in container-specific locations, where they are available to all the applications that run in the container.
 +
 +
This ''shared deployment scheme'' for <code>SmartGears</code> is largely dictated by the need to share state about the container across applications, which remain otherwise isolated in the classloader hierarchies defined by the container. A shared installation achieves that in a container-independent manner.
 +
 
 
The shared scheme has additional advantages:
 
The shared scheme has additional advantages:
SmartGears does not need to be embedded in applications, which lowers their packaging requirements and size of distribution. As we discuss below, requirements on applications are limited to resource descriptors;
+
 
the management functions provided by SmartGears are uniformly and consistently applied to all applications that run in a given container;
+
* <code>SmartGears</code> does not need to be embedded in applications, which lowers their packaging requirements and size of distribution. As we've discussed [[#Requirements|above]], requirements on applications are limited to resource descriptors;
SmartGears can be updated simply by updating its shared installation, i.e. without requiring a repackaging of all the applications that run in the container;
+
 
Of course, shared installations emphasise the importance of limiting 3rd-party dependencies to a minimum, avoiding altogether very common, general purpose dependencies that may clash with versions used in applications stacks. Of course, this requirement would exist even if SmartGears were packaged with applications, but it stands even stronger against shared installations, which expose SmartGears libraries also to all applications that run in the container, including those that do not need to be managed by SmartGears. We minimise this risk by basing SmartGears on “microlibs”, as we have discussed above.
+
* the management functions provided by <code>SmartGears</code> are uniformly and consistently applied to all applications that run in a given container;
 +
 
 +
* <code>SmartGears</code> can be updated simply by updating its shared installation, i.e. without requiring a repackaging of all the applications that run in the container;
 +
 
 +
Of course, shared installations emphasise the importance of limiting 3rd-party dependencies to a minimum, avoiding altogether very common, general purpose dependencies that may clash with versions used in applications stacks. Of course, this requirement would exist even if <code>SmartGears</code> were packaged with applications, but it stands even stronger against shared installations, which expose <code>SmartGears</code> libraries also to all applications that run in the container, including those that do not need to be managed by <code>SmartGears</code>. We minimise this risk by basing <code>SmartGears</code> on microlibs, as we have discussed above.
  
 
= Logging =
 
= Logging =
SmartGears uses Slf4j for its own logs, and its distribution includes Logback as the Slf4j binding . The installation scripts then copy a default logback.xml configuration file in the container-specific locations where SmartGears libraries are installed. The default configuration defines a file-based appender for the logs, where the current log file is $GHN_HOME/ghn.log and files are rolled daily and kept for a maximum of 30 days. In all cases, SmartGears logs are kept completely independent from the container’s and application,
+
 
Slf4j and Logback are the only concession that the SmartGears distribution makes to 3rd-party dependencies. The concession is necessary, as it could be only be avoided via a custom logging framework or a custom repackaging of any framework of choice. Unfortunately, we cannot pursue either option in SmartGears because many of its  libraries are used also in other contexts (e.g. in the FWS).  
+
<code>SmartGears</code> uses <code>Slf4j</code> for its own logs, and its distribution includes <code>Logback</code> as the <code>Slf4j</code> binding . The installation scripts then copy a default <code>logback.xml</code> [#Default Logging Configuration| configuration file]] in the container-specific locations where <code>SmartGears</code> libraries are installed. The default configuration defines a file-based appender for the logs, where the current log file is <code>$GHN_HOME/ghn.log</code> and files are rolled daily and kept for a maximum of 30 days.  
As a result, SmartGears may interfere with applications that use Slf4j. While the Slf4j API does not create problems (regardless of the version used by applications), Slf4j bindings might.  In particular, we distinguish the following cases::
+
 
applications that bundle the Slf4j API and Logback (i.e. make the same choices as SmartGears, regardless of versions) will experience no interference, in that their Logback configuration will be handled separately from SmartGears’;
+
<code>Slf4j<code> and <code>Logback</code> are the only concession that <code>SmartGears</code> makes to 3rd-party dependencies. The concession is necessary, as it could be only be avoided via a custom logging framework or a custom repackaging of any framework of choice. Unfortunately, we cannot pursue either option in <code>SmartGears</code> because many of its  libraries are used also in other contexts (e.g. in the <code>FWS</code>).  
applications that bundle the Slf4j API and an Slf4j binding other than Logback will be warned that the binding of the Slf4j API is ambiguous, as two different options are available in the classpath. While Slf4j does not guarantee it, our tests show that the application’s binding will prevail and no interference will be observed by the application. In this case, the net effect is the same as in case 1.;
+
 
applications that bundle the Slf4j API but not an Slf4j binding will encounter classloading errors at startup. This configuration is however highly unlikely in practice, because if Slf4j bindings are provided by the containerthen also the Slf4j API should be, as in the next case;
+
As a result, <code>SmartGears</code> may interfere with applications that use <code>Slf4j</code>. While the <code>Slf4j</code> API does not create problems (regardless of the version used by applications), <code>Slf4j</code> bindings might.  In particular, we distinguish the following cases:
applications that bundle neither the Slf4j API nor an Slf4j binding (i.e. expect the API to be provided by the container) will find that their logs in SmartGears’ logfile and their configurations, if any, ignored;;
+
 
applications that bundles an Slf4j binding but do not bundle the Slf4j API (i.e. expect it to be provided by the container), will find that their logs where they configure them to be;
+
# applications that bundle the <code>Slf4j</code> API and <code>Logback</code> (i.e. make the same choices as <code>SmartGears</code>, regardless of versions) will experience no interference, in that their <code>Logback</code> configuration will be handled separately from <code>SmartGears</code>’;
 +
 
 +
# applications that bundle the <code>Slf4j</code> API and an <code>Slf4j</code> binding other than <code>Logback</code> will be warned that the binding of the <code>Slf4j</code> API is ambiguous, as two different options are available in the classpath. While <code>Slf4j</code> does not guarantee it, our tests show that the application’s binding will prevail and no interference will be observed by the application. In this case, the net effect is the same as in case 1.;
 +
 
 +
# applications that bundle the <code>Slf4j</code> API but no <code>Slf4j</code> binding will encounter classloading errors at startup. This configuration is however highly unlikely in practice, because if <code>Slf4j</code> bindings are provided by the container then also the <code>Slf4j</code> API should be, as in the next case;
 +
 
 +
# applications that bundle neither the <code>Slf4j</code> API nor an <code>Slf4j</code> binding (i.e. expect the API to be provided by the container) will find that their logs in <code>SmartGears</code>’ logfile and their configurations, if any, ignored;
 +
 
 +
# applications that bundles an <code>Slf4j</code> binding but do not bundle the <code>Slf4j</code> API (i.e. expect it to be provided by the container), will find that their logs where they configure them to be;
 +
 
 
Overall:
 
Overall:
cases 1. and 2. are most likely for applications that are fully unaware of gCube and their use as gCube resources.
+
 
case 3. should not occur often in practice, as it is likely to be a configuration error of the application.
+
* cases 1. and 2. are most likely for applications that are fully unaware of <code>gCube</code> and their use as <code>gCube</code> resources;
case 4. and case 5. are likely to apply when containers, like SmartGears, adopt Slf4j and applications are packaged with an awareness of this arrangement. A key scenario for this is that of gCube-aware applications, which are packaged and developed with the expectation of a SmartGears-enabled container. Case 4. does not require configuration while case 5 separates application logs from SmartGears logs and, depending on the configuration, from the logs of other applications.
+
* case 3. should not occur often in practice, as it is likely to be a configuration error of the application;
 +
* case 4. and case 5. are likely to apply when containers, like <code>SmartGears</code>, adopt <code>Slf4j</code> and applications are packaged with an awareness of this arrangement. A key scenario for this is that of [[#gCube-Aware Applications|gCube-aware applications]], which are packaged and developed with the expectation of a <code>SmartGears</code>-enabled container. Case 4. does not require configuration while case 5 separates application logs from <code>SmartGears</code> logs and, depending on the configuration, from the logs of other applications.
  
 
= API Extensions =
 
= API Extensions =
SmartGears extends all managed applications with servlets that can be used for remote management of the applications. These "API extensions" are registered at URLs under the gcube root, which is in turn immetely under the application root.
+
 
 +
<code>SmartGears</code> extends all managed applications with servlets that can be used for remote management of the applications. These ''API extensions'' are registered at URLs under the <code>gcube</code> root, which is in turn immetely under the application root.
 +
 
 
Currently, the available extensions can answer the following HTTP requests:
 
Currently, the available extensions can answer the following HTTP requests:
GET /gcube/resource  
+
 
returns an HTML splash page for the application, which reports its key properties as a resource and includes links to its resource profile and resource configuration;
+
* <code>GET /gcube/resource</code>
GET /gcube/resource/profile
+
:returns an HTML splash page for the application, which reports its key properties as a resource and includes links to its resource profile and resource configuration;
returns the resource profile for the application, in its standard XML serialisation;
+
 
GET /gcube/resource/profile  
+
* <code>GET /gcube/resource/profile</code>
returns the application descriptor, i.e. the context of gcube-app.xml;
+
: returns the resource profile for the application, in its standard XML serialisation;
GET /gcube/resource/lifecycle
+
 
returns the current state of the application as the simple content of a state XML element (e.g. <state>READY</state>);
+
<code>GET /gcube/resource/profile</code>
POST /gcube/resource/lifecycle
+
:returns the application descriptor, i.e. the context of <code>gcube-app.xml</code>;
changes the current state of the application to the simple content of a state XML element provided as the body of the request (e.g. <state>FAILED</state>);
+
 
GET /gcube/resource/scopes
+
* <code>GET /gcube/resource/lifecycle</code>
returns the current scopes of the application as the simple content of one or more scope XML elements nested inside a scopes element (e.g. <scopes> <scope>/gcube/devsec</scope><scope>/gcube/devNext</scope></scopes>);
+
:returns the current state of the application as the simple content of a <code>state</code> XML element (e.g. <code><state>READY</state></code>);
POST /gcube/resource/scopes
+
 
adds or remove a scope to or from the application. Scopes are added as the simple content of a scope XML element provided as the body of the request (e.g. <scope>/gcube/devsec</scope>. Scopes are removed analogously, except that the scope element provided in the body has a delete attribute set to true (e.g. <scopes> <scope delete=”true”>/gcube/devsec</scope>);
+
* <code>POST /gcube/resource/lifecycle</code>
 +
: changes the current state of the application to the simple content of a <code>state</code> XML element provided as the body of the request (e.g. <code><state>FAILED</state></code>);
 +
 
 +
* <code>GET /gcube/resource/scopes</code>
 +
:returns the current scopes of the application as the simple content of one or more <code>scope</code> XML elements nested inside a <code>scopes</code> element (e.g. <code><scopes> <scope>/gcube/devsec</scope><scope>/gcube/devNext</scope></scopes></code>);
 +
 
 +
* <code>POST /gcube/resource/scopes</code>
 +
:adds or remove a scope to or from the application. Scopes are added as the simple content of a <code>scope</code> XML element provided as the body of the request (e.g. <code><scope>/gcube/devsec</scope></code>. Scopes are removed analogously, except that the <code>scope</code> element provided in the body has a delete attribute set to true (e.g. <code><scopes> <scope delete=”true”>/gcube/devsec</scope></code>);
  
 
= gCube-Aware Applications =
 
= gCube-Aware Applications =
While SmartGears can make resources out of arbitrary applications, it does not exclude that some applications may still be designed explicitly as gCube resources. These applications may need to inspect their properties as resources, or the properties of their container (e.g. current status, active sharing policies, configuration, etc), or they may need to react to events in their own resource lifecycle, or again in the lifecycle of their container.  Of course, gCube itself is and will continue to be the main source of such "gCube-aware" applications.
+
 
When it comes to developing gCube-aware applications, SmartGears must become visible.  For this, SmartGears expose a selection of its APIs through the ServletContext of the application, the common denominator of all Servlet-based applications.  
+
While <code>SmartGears</code> can make resources out of arbitrary applications, it does not exclude that some applications may still be designed explicitly as <code>gCube</code> resources. These applications may need to inspect their properties as resources, or the properties of their container (e.g. current status, active sharing policies, configuration, etc), or they may need to react to events in their own resource lifecycle, or again in the lifecycle of their container.  Of course, <code>gCube</code> itself is and will continue to be the main source of such ''<code>gCube</code>-aware'' applications.
The APIs are rooted in an ApplicationContext that represents the application as a resource. Through the ApplicationContext the application can get to the resource profile, the resource configuration in  gcube-app.xml, the resource lifecycle, and the subscription mechanisms that relate to the resource lifecycle. The ApplicationContext exposes also the ContainerContext, which gives access to similar information and mechanisms about the container in which the application is running.
+
 
For further convenience, SmartGears includes a common-smartgears-app library, which simplifies the task of accessing the ApplicationContext from  within any implementation stack. The library leverages the annotations in the Servlet 3 specifications to transparently add a ServletContextListener to all the applications that include the library in their distribution.  
+
When it comes to developing <code>gCube</code>-aware applications, <code>SmartGears</code> must become visible.  For this, <code>SmartGears</code> expose a selection of its APIs through the <code>ServletContext</code> of the application, the common denominator of all <code>Servlet</code>-based applications.  
At application startup, the listener extracts the ApplicationContext from the ServletContext and registers it on a ContextProvider. The provider is statically accessible to the application and can make available the ApplicationContext as follows:
+
 
ApplicationContext ctx = ContextProvider.get()
+
The APIs are rooted in an <code>ApplicationContext</code> that represents the application as a resource. Through the <code>ApplicationContext</code> the application can get to the resource profile, the resource configuration in  <code>gcube-app.xml</code>, the resource lifecycle, and the subscription mechanisms that relate to the resource lifecycle. The <code>ApplicationContext</code> exposes also the <code>ContainerContext</code>, which gives access to similar information and mechanisms about the container in which the application is running.
The application can then access all the information and notification mechanisms that are directly or indirectly provided by SmartGears.
+
 
gCube-aware applications that use Maven can specify their dependencies to Smartgears as shown in the Appendices.  
+
For further convenience, <code>SmartGears</code> includes a <code>common-smartgears-app</code> library, which simplifies the task of accessing the <code>ApplicationContext</code> from  within any implementation stack. The library leverages the annotations in the <code>Servlet</code> 3 specifications to transparently add a <code>ServletContextListener</code> to all the applications that include the library in their distribution.  
 +
 
 +
At application startup, the listener extracts the <code>ApplicationContext</code> from the <code>ServletContext</code> and registers it on a <code>ContextProvider</code>. The provider is statically accessible to the application and can make available the <code>ApplicationContext</code> as follows:
 +
 
 +
<source lang="java5">
 +
ApplicationContext ctx = ContextProvider.get()
 +
</source>
 +
 
 +
The application can then access all the information and notification mechanisms that are directly or indirectly provided by <code>SmartGears</code>.
 +
 
 +
<code>gCube</code>-aware applications that use <code>Maven</code> can specify their dependencies to <code>Smartgears</code> as shown in the [[#Maven Dependencies|Appendices]].
 +
 
 +
== Authorization ==
 +
 
 +
Authorization is transparent for all the Smartgears apps. The TOKEN is automatically read and resolved on every call.
 +
In case the developer needs to know the current context of the call or the client that is trying to access the webapp, two ThreadLocal variables are set in the current Thread:
 +
* CurrentContext;
 +
* AuthorizationProvider.
 +
 
 +
The <code>ScopeProvider.instance.get()</code> method returns a <code>String</code> representing the current context.
 +
 
 +
The <code>AuthorizationProvider.instance.get()</code> method returns a <code>Caller</code> object containing the identifier and roles of the caller.
 +
 
 +
== Accounting ==
 +
 
 +
Calls received by a Smartgears enable service are automatically accounted.
 +
The method name used is extracted from the PathInfo (in case of REST service) or from the client.
 +
Another way to set internally a custom method name is to set the InnerMethodName thread local.
 +
 
 +
<code> InnerMethodName.instance.set("methodnameToAccount") </code>
 +
 
 +
 
 +
== Intialization ==
 +
 
 +
The smartgears framwork allows services to make some work at initialization-time (e.g. search for resources, register to a topic etc.).
 +
To enable this functionality is sufficent to create a class that implements the ApplicationManager class.
 +
 
 +
<source lang="java">
 +
..
 +
import org.gcube.smartgears.ApplicationManager;
 +
..
 +
 
 +
public class MyAppManager implements ApplicationManager {
 +
 
 +
private static Logger logger = LoggerFactory.getLogger(MyAppManager.class);
 +
 
 +
ApplicationContext ctx = ContextProvider.get();
 +
 
 +
@Override
 +
public void onInit() {
 +
  //do something on init
 +
}
 +
 
 +
@Override
 +
public void onShutdown() {
 +
  //do something on shutdown
 +
}
 +
}
 +
</source>
 +
 
 +
The last thing to do is to declare the servlet implementation class as ManagedBy the MyAppManager class.
 +
 
 +
<source lang="java">
 +
..
 +
import org.gcube.smartgears.annotations.ManagedBy;
 +
..
 +
@WebService(portName = "TestPort",
 +
serviceName = "testinterface",
 +
targetNamespace = "http://gcube-system.org/test",
 +
endpointInterface = "org.gcube.test.ServiceInterface")
 +
@ManagedBy(MyAppManager.class)
 +
public class FactoryTest implements ServiceInterface {
 +
 
 +
..
 +
 
 +
}
 +
</source>
 +
 
 +
The implemented ApplicationManager keep the state per context. The ApllicationManager related to current context can be recovered on the managed class as follow:
 +
 
 +
<source lang="java">
 +
..
 +
import org.gcube.smartgears.ApplicationManagerProvider;
 +
 
 +
..
 +
MyAppManager appManager = (MyAppManager)ApplicationManagerProvider.get();
 +
..
 +
</source>
  
 
= Appendices =
 
= Appendices =
  
 
== Container Descriptor ==
 
== Container Descriptor ==
SmartGears manages containers according to the instructions found in a $GHN_HOME/container.xml descriptor. We can illustrate the structure of this descriptor by example, greying out elements that are optional:  
+
 
 +
<code>SmartGears</code> manages containers according to the instructions found in a <code>$GHN_HOME/container.xml</code> descriptor. We can illustrate the structure of this descriptor by example, commenting out elements that are optional:  
 +
 
 +
<source lang="xml">
 
<container mode='online'>
 
<container mode='online'>
     <hostname>acme.org</hostname>
+
      
 +
    <hostname>acme.org</hostname>
 
     <port>8081</port>   
 
     <port>8081</port>   
 +
   
 
     <infrastructure>gcube</infrastructure>
 
     <infrastructure>gcube</infrastructure>
     <vo>devsec</vo>
+
     <!--<token>tokenContext1</token>-->
     <vo>devNext</vo>
+
     <!--<token>tokenContext2</token>-->
<persistence>some/alternative/location</persistence>
+
   
 +
    <!--<persistence location="/some/custom/location</persistence" /> //THE VALUE MUST BE A VALID DIRECTORY -->
 +
   
 
     <site>
 
     <site>
 
       <country>it</country>
 
       <country>it</country>
Line 175: Line 324:
 
       <longitude>12.5000</longitude>
 
       <longitude>12.5000</longitude>
 
     </site>
 
     </site>
     <property name='prop1' value='val1' />  
+
      
     <property name='prop2' value='val2' />  
+
    <!--<property name='prop1' value='val1' />-->  
     <publication-frequency>60</publication-frequency>
+
     <!--<property name='prop2' value='val2' />-->
 +
 +
     <!--<publication-frequency>60</publication-frequency>-->
 +
 
 
</container>
 
</container>
 +
</source>
  
 
== Application Descriptor ==
 
== Application Descriptor ==
SmartGears manages applications that include a WEB-INF/gcube-app.xml descriptor in their distributions. We can illustrate the structure of this descriptor by example, greying out elements that are optional:  
+
 
 +
<code>SmartGears</code> manages applications that include a <code>WEB-INF/gcube-app.xml</code> descriptor in their distributions. We can illustrate the structure of this descriptor by example, commenting out elements that are optional:  
 +
 
 +
<source lang="xml">
 
<application mode="online">
 
<application mode="online">
 +
 
<name>lorem</name>
 
<name>lorem</name>
 
<group>ipsum</group>
 
<group>ipsum</group>
 
<version>1.0</version>
 
<version>1.0</version>
<description>Lorem ipsum dolor sit amet...</description>
+
 
<persistence>/some/custom/location</persistence>  
+
        <!--<description>Lorem ipsum dolor sit amet...</description>-->
  <exclude>/some/app/url</exclude>
+
 
<exclude>/some/other/custom/url</exclude>  
+
        <!--<persistence location="/some/custom/location"</persistence/> //THE VALUE MUST BE A VALID DIRECTORY -->
 +
   
 +
        <!--<exclude>/some/app/url</exclude>-->
 +
        <!--<exclude>/some/other/custom/url</exclude>-->
 +
        <!--<exclude handlers='request-accounting'>/*</exclude>  //excludes accounting handler for all paths in the application -->
 +
 
</application>
 
</application>
 +
</source>
  
 
== Default Logging Configuration ==
 
== Default Logging Configuration ==
 +
 +
<source lang="xml">
 
<configuration>
 
<configuration>
 
     <appender name="FILE" class="ch.qos.logback.core.FileAppender">
 
     <appender name="FILE" class="ch.qos.logback.core.FileAppender">
Line 212: Line 377:
 
   </root>
 
   </root>
 
</configuration>
 
</configuration>
 +
</source>
  
 
== Maven Dependencies ==
 
== Maven Dependencies ==
  
gCube-aware applications that use Maven can resolve their dependencies to SmartGears by adding the following to their POMs:
+
<code>gCube-aware</code> applications that use <code>Maven</code> can resolve their dependencies to <code>SmartGears</code> by adding the following to their <code>POM</code>s:
 +
 
 +
<source lang="xml">
 
           <dependencyManagement>
 
           <dependencyManagement>
 
                         <dependencies>
 
                         <dependencies>
Line 229: Line 397:
 
</dependencies>
 
</dependencies>
 
</dependencyManagement>
 
</dependencyManagement>
...
+
          ...
 
<dependencies>
 
<dependencies>
...
+
          ...
 
<dependency>
 
<dependency>
 
<groupId>org.gcube.core</groupId>
 
<groupId>org.gcube.core</groupId>
Line 240: Line 408:
 
<artifactId>common-smartgears</artifactId>
 
<artifactId>common-smartgears</artifactId>
 
</dependency>
 
</dependency>
                                ….
+
                  ….
 
</dependencies>
 
</dependencies>
The first dependency is to SmartGears's “Bills of Materia”l (BOM), a POM-only Maven artefact which specifies dependencies to all the SmartGears libraries. By importing it in the dependencyManagement section of their POMs, applications make sure that dependencies to SmartGears libraries:
+
</source>
have provided scope, i.e. will not be bundled with the applications;
+
 
are the latest available versions, those with which the applications will be built and then managed in production.
+
The first dependency is to <code>SmartGears</code>'s “Bills of Materia”l (<code>BOM</code>), a <code>POM</code>-only <code>Maven</code> artefact which specifies dependencies to all the <code>SmartGears</code> libraries. By importing it in the <code>dependencyManagement</code> section of their <code>POM</code>s, applications make sure that dependencies to <code>SmartGears</code> libraries:
The version LATEST matches the latest release of the BOM, which is always kept in sync with the latest release of SmartGears. During gCube builds, LATEST is replaced with a specific version number, so that the reproducibility of release builds is always guaranteed.
+
 
The other two concrete dependencies are to common-smartgears-app and common-smartgears, and rely on versions and scopes defined in the BOM.
+
*have <code>provided</code> scope, i.e. will not be bundled with the applications;
 +
* are the latest available versions, those with which the applications will be built and then managed in production.
 +
 
 +
The version <code>LATEST</code> matches the latest release of the <code>BOM</code>, which is always kept in sync with the latest release of <code>SmartGears</code>. During <code>gCube</code> builds, <code>LATEST</code> is resolved to and replaced with a specific version number, so that the reproducibility of release builds is always guaranteed.
 +
 
 +
The other two concrete dependencies are to <code>common-smartgears-app</code> and <code>common-smartgears</code>, and rely on versions and scopes defined in the <code>BOM</code>.

Latest revision as of 15:48, 18 January 2019

SmartGears is a set of Java libraries that turn Servlet-based containers and applications into gCube resources, transparently.

In this document, we motivate SmartGears and explain how it improves over existing gCube solutions. The discussion is relevant to node and infrastructure managers, who perform and maintain Smartgears installations, and to developers, who package or write software for a gCube infrastructure.

Rationale

What does it mean to turn software applications and containers into gCube resources?

We start by revisiting the goals of “Software-As-Resource” (SaR) and “Container-as-Resource” (CaR), i.e. the core mission of gCube’s Enabling Layer. We then take stock of how far we have come towards achieving these goals, motivating Smartgears as our latest attempt to go further still.

Software-as-Resource

A piece of software is a gCube resource if we can manage it in a gCube infrastructure. This means that we can do a number of things with the software, including:

  • discover where it is deployed, so as to use it without hard coded knowledge of its location.
For this, we need to describe each and every software deployment, and publish these descriptions, or profiles, in the infrastructure;
  • monitor and change the status of its deployments, so as to take actions when they are not in an operational status (e.g. redeploy the software, or at least prevent discovery and usage of the deployments).
For this, we need to track their current status, report it in the profiles we publish, and republish the profiles when the status changes;
  • dedicate its deployments to certain groups of users, in the sense that only users in those groups can use them.
We can change the sharing policies of individual deployments at any time, i.e. share them across more or less groups. We can also grant different privileges to different types of users within given groups.

Publication, discovery, lifecycle management, controlled sharing are the pillars of resource management in gCube. Yet relying on humans to compile deployment profiles, publish them in the infrastructure, keep track and change the status of deployments, or enforce sharing policies is all but practical. In some cases, it is downright impossible. We need instead automated solutions that live alongside each and every deployment and help us turn it into a resource we can manage. Smartgears is one such solution.

Container-as-Resource

When we pursue SaR, we are not after any possible software. We focus on software that can be used over the network, such as distributed applications and network services. Software deployments then correspond to software endpoints.

Typically, software endpoints run within containers and, in gCube, containers can be resources in their own right, the so-called gCube Hosting Nodes (gHNs).

Managing gHNs is a way to manage multiple endpoints simultaneously (e.g. deactivate a gHN means to deactivate a set of endpoints at once). Equally, it is a way to manage underlying hardware resources (e.g. dedicate a gHN to selected groups of users).

This is a notion of "Container-as-Resource" (CaR), and it raises the same requirements as SaR, including publication and discovery, lifecycle management, and controlled sharing. Smartgears helps us meet these requirements too, i.e. turns containers as well as the endpoints therein into gCube resources.

Big Frameworks

Traditionally, enabling SaR and CaR has been the main value proposition of the gCube Core Framework (gCF). The way gCF delivers that value has limitations, however:

  • gCF is a framework to develop SaR: its class hierarchies, interfaces, callbacks, and helper objects guide and simplify the task of writing software that directly meets our management requirements. Simply put, gCF lets us develop SaR specifically and exclusively for gCube. This "closed-world" assumption is not a bad thing insofar as all the SaR we need is part of gCube itself. Indeed, gCF has helped us a great deal to grow gCube consistently. However, it does becomes a problem when we want to:
  • reuse gCube software externally to the infrastructure;
  • bring existing software into the infrastructure;
  • encourage third parties to develop software for the infrastructure.
It also becomes a problem if we wish to deviate from the type of SaR that we can develop with gCF, which brings us to the next point:
  • with gCF, the only CaR we get is the Globus container, and the only type of SaR we can enable are JAX-RPC services that run in that container. We cannot:
  • develop SaR as a Rest service, or as a plain Web Application;
  • develop SaR using modern standards for Soap services (e.g. JAX-WS);
  • run SaR in popular, modern, and performant application containers (e.g. Tomcat, Jetty, full-blown JEE servers).
Overall, we are severely limited in our choice of development stack. This creates an evolution problem for gCube, as well as an obstacle to its adoption and further growth.
  • since gCF sits right at the top of the stack of the SaR we produce, its APIs are public: if we change them we break at once a large number of gCube services. Again, this inhibits the evolution of the system.

Overall, there are at least two themes in the issues above:

  • age: gCF, Globus, and their technological context are well dated by now;
  • visibility: gCF sits right at the top of the software’s stack and right in the middle of its design.

Less is More

If we look at gCF as an ageing solution, the temptation is to revamp and expand: align with new standards for Soap services, open up to Rest services, and perhaps move towards modern containers. The is substantial work, however, and it would have a dramatic impact on gCube. It would also be short-sighted work, as a cycle of five years may well bring us back where we are now.

We believe instead that visibility is the key problem to address: if gCF weren’t visible to begin with, its age would be of little of no concern. With Smartgears we propose the same net value as gCF, but deliver it in a completely different fashion: we move away from frameworks and make Smartgears invisible to the software, not part of its stack at all. As a result, gCube is invisible too and any software can run in the infrastructure: SaR becomes a nature that software acquires at runtime;

Indeed, Smartgears has little requirements to raise against the software. As we shall see, all we ask of software is to be based on the Servlet specifications, which define the hooks that we need to track its lifecycle and its use. The software is thus a Web Application and may more specifically be a Soap service, a Rest service, or a generic Web Application. It may adopt different standards and technologies (e.g. JAX-RPC, JAX-WS, JAX-RS, but also Dependency Injection technologies, persistence technologies, etc.). And of course it may run in any container that is Servlet-compliant (Web Containers, Application Servers).

Finally, the evolution of Smartgears is inconsequential for the software: most of the APIs of Smartgears remain private to Smartgears.

Featherweight Relations

Smartgears and the FeatherWeight Stack (FWS) are both solutions based on microlibs, and in fact share a number of them.

Smartgears is the logical counterpart of the FWS: if the first turns Java software into gCube resources, the second enables other Java software to call such resources. Together, Smartgears and the FWS provide a logical replacement of gCF and gCore.

The FWS is a stack, however, i.e. a direct or indirect dependency of clients. In contrast, Smartgears live in the runtime of software but it does not need to be a compile or runtime dependency for it (but see gCube-aware applications).

Requirements

Containers and applications need a minimal set of requirements before SmartGears can turn them into gCube resources:

  • containers must comply with version 3 of the Servlet specifications;
  • applications must include at least one gcube-app.xml configuration file alongside their deployment descriptor (i.e.. under /WEB-INF);

In addition:

  • node managers must define a GHN_HOME environment variable that resolves to a location where SmartGears can find a container.xml configuration file;.

Starting from version 3, the Servlet specifications allow SmartGears to intercept relevant events in the lifecycle of individual applications whilst being shared across all applications, in line with the deployment scheme of SmartGears. In particular, the specifications introduce a ServletContextInitializer interface that SmartGears implements to be notified of application startup. The specifications also allow programmatic registration of filters and servlets, which SmartGears uses to transparently manage applications without the need of additional configuration in their web.xml descriptor.

Configuration is thus limited to WEB-INF/gcube-app.xml and $GHN_HOME/container.xml, which provide the configuration of, respectively, the application and the container as gCube resources. We discuss their contents in the Appendices.

Distribution

Smartgears is distributed as a tarball that contains the libraries, scripts, and configuration files required to install Smartgears in a given container, and to maintain the installation over time. Instructions on how to download, install and maintain Smartgears are available in the SmartGears_Web_Hosting_Node_(wHN)_Installation and we do not duplicate them here.

Components

The libraries that comprise Smartgears and are bundled in its distribution are also available in our Maven repository, like any other gCube component. They can thus be resolved as Maven dependencies whenever applications need to introspect on their configuration and status as gCube resources. We discuss below this class of gCube-aware applications.

The vast majority of Smartgears libraries are “microlibs”, i.e. Java libraries with:

  • a narrow functional focus, i.e. provide one and only one type of functionality;
  • contained dependencies, i.e. depend only on other microlibs and the JDK.

Using microlibs reflects a commitment to provide support which is:

  • modular: client assemble microlibs to obtain no more and no less than the functionality they need. This avoids the spurious dependencies that are often introduced by multi-function libraries, hence limits the impact of evolving individual libraries;
  • unobtrusive: clients do not inherit from microlibs runtime dependencies on common, general-purpose third-party libraries. This limits the risk that such dependencies may clash with versions already available in their runtimes;
  • lightweight: as an implication of modular and non-intrusive support, microlibs do not inflate the size of client runtimes.

SmartGears includes the following microlibs:

  • org.gcube.core:common-smartgears: the main library in SmartGears, contains all the components that provide the management logic required to turn applications and containers into gCube resources. All the other libraries are direct or indirect dependencies of common-smartgears;
  • org.gcube.core:common-events: a general-purpose, annotation-based eventing library used by the components in common-smartgears to sync with each other actions in a loosely-coupled manner;
  • org.gcube.core:common-validator: a general-purpose, annotation-based library for object state validation used in common-smartgears to validate configuration objects;
  • org.gcube.core:common-scope: a library with facilities related to gCube scope management;
  • org.gcube.resources:common-gcore-resources: a library with the object bindings for the gCube resource model used in SmartGears to model application and container resource profiles ;
  • org.gcube.resources:registry-publisher: a client library for the gCube Registry service used in common-smartgears to publish application and container profiles;
  • org.gcube.core:common-smartgears-app: a library that provides mechanisms to expose selected APIs in common-smartgears to gCube-aware applications;

The distribution of SmartGears includes of course the transitive closure of the libraries above. It also includes the only 3rd party dependencies of SmartGears, namely Slf4j and Logback, which we discuss below in regard to logging.

Deployment Scheme

The installation scripts included in the SmartGears distribution copy the SmartGears libraries in container-specific locations, where they are available to all the applications that run in the container.

This shared deployment scheme for SmartGears is largely dictated by the need to share state about the container across applications, which remain otherwise isolated in the classloader hierarchies defined by the container. A shared installation achieves that in a container-independent manner.

The shared scheme has additional advantages:

  • SmartGears does not need to be embedded in applications, which lowers their packaging requirements and size of distribution. As we've discussed above, requirements on applications are limited to resource descriptors;
  • the management functions provided by SmartGears are uniformly and consistently applied to all applications that run in a given container;
  • SmartGears can be updated simply by updating its shared installation, i.e. without requiring a repackaging of all the applications that run in the container;

Of course, shared installations emphasise the importance of limiting 3rd-party dependencies to a minimum, avoiding altogether very common, general purpose dependencies that may clash with versions used in applications stacks. Of course, this requirement would exist even if SmartGears were packaged with applications, but it stands even stronger against shared installations, which expose SmartGears libraries also to all applications that run in the container, including those that do not need to be managed by SmartGears. We minimise this risk by basing SmartGears on microlibs, as we have discussed above.

Logging

SmartGears uses Slf4j for its own logs, and its distribution includes Logback as the Slf4j binding . The installation scripts then copy a default logback.xml [#Default Logging Configuration| configuration file]] in the container-specific locations where SmartGears libraries are installed. The default configuration defines a file-based appender for the logs, where the current log file is $GHN_HOME/ghn.log and files are rolled daily and kept for a maximum of 30 days.

Slf4j<code> and <code>Logback are the only concession that SmartGears makes to 3rd-party dependencies. The concession is necessary, as it could be only be avoided via a custom logging framework or a custom repackaging of any framework of choice. Unfortunately, we cannot pursue either option in SmartGears because many of its libraries are used also in other contexts (e.g. in the FWS).

As a result, SmartGears may interfere with applications that use Slf4j. While the Slf4j API does not create problems (regardless of the version used by applications), Slf4j bindings might. In particular, we distinguish the following cases:

  1. applications that bundle the Slf4j API and Logback (i.e. make the same choices as SmartGears, regardless of versions) will experience no interference, in that their Logback configuration will be handled separately from SmartGears’;
  1. applications that bundle the Slf4j API and an Slf4j binding other than Logback will be warned that the binding of the Slf4j API is ambiguous, as two different options are available in the classpath. While Slf4j does not guarantee it, our tests show that the application’s binding will prevail and no interference will be observed by the application. In this case, the net effect is the same as in case 1.;
  1. applications that bundle the Slf4j API but no Slf4j binding will encounter classloading errors at startup. This configuration is however highly unlikely in practice, because if Slf4j bindings are provided by the container then also the Slf4j API should be, as in the next case;
  1. applications that bundle neither the Slf4j API nor an Slf4j binding (i.e. expect the API to be provided by the container) will find that their logs in SmartGears’ logfile and their configurations, if any, ignored;
  1. applications that bundles an Slf4j binding but do not bundle the Slf4j API (i.e. expect it to be provided by the container), will find that their logs where they configure them to be;

Overall:

  • cases 1. and 2. are most likely for applications that are fully unaware of gCube and their use as gCube resources;
  • case 3. should not occur often in practice, as it is likely to be a configuration error of the application;
  • case 4. and case 5. are likely to apply when containers, like SmartGears, adopt Slf4j and applications are packaged with an awareness of this arrangement. A key scenario for this is that of gCube-aware applications, which are packaged and developed with the expectation of a SmartGears-enabled container. Case 4. does not require configuration while case 5 separates application logs from SmartGears logs and, depending on the configuration, from the logs of other applications.

API Extensions

SmartGears extends all managed applications with servlets that can be used for remote management of the applications. These API extensions are registered at URLs under the gcube root, which is in turn immetely under the application root.

Currently, the available extensions can answer the following HTTP requests:

  • GET /gcube/resource
returns an HTML splash page for the application, which reports its key properties as a resource and includes links to its resource profile and resource configuration;
  • GET /gcube/resource/profile
returns the resource profile for the application, in its standard XML serialisation;

GET /gcube/resource/profile

returns the application descriptor, i.e. the context of gcube-app.xml;
  • GET /gcube/resource/lifecycle
returns the current state of the application as the simple content of a state XML element (e.g. <state>READY</state>);
  • POST /gcube/resource/lifecycle
changes the current state of the application to the simple content of a state XML element provided as the body of the request (e.g. <state>FAILED</state>);
  • GET /gcube/resource/scopes
returns the current scopes of the application as the simple content of one or more scope XML elements nested inside a scopes element (e.g. <scopes> <scope>/gcube/devsec</scope><scope>/gcube/devNext</scope></scopes>);
  • POST /gcube/resource/scopes
adds or remove a scope to or from the application. Scopes are added as the simple content of a scope XML element provided as the body of the request (e.g. <scope>/gcube/devsec</scope>. Scopes are removed analogously, except that the scope element provided in the body has a delete attribute set to true (e.g. <scopes> <scope delete=”true”>/gcube/devsec</scope>);

gCube-Aware Applications

While SmartGears can make resources out of arbitrary applications, it does not exclude that some applications may still be designed explicitly as gCube resources. These applications may need to inspect their properties as resources, or the properties of their container (e.g. current status, active sharing policies, configuration, etc), or they may need to react to events in their own resource lifecycle, or again in the lifecycle of their container. Of course, gCube itself is and will continue to be the main source of such gCube-aware applications.

When it comes to developing gCube-aware applications, SmartGears must become visible. For this, SmartGears expose a selection of its APIs through the ServletContext of the application, the common denominator of all Servlet-based applications.

The APIs are rooted in an ApplicationContext that represents the application as a resource. Through the ApplicationContext the application can get to the resource profile, the resource configuration in gcube-app.xml, the resource lifecycle, and the subscription mechanisms that relate to the resource lifecycle. The ApplicationContext exposes also the ContainerContext, which gives access to similar information and mechanisms about the container in which the application is running.

For further convenience, SmartGears includes a common-smartgears-app library, which simplifies the task of accessing the ApplicationContext from within any implementation stack. The library leverages the annotations in the Servlet 3 specifications to transparently add a ServletContextListener to all the applications that include the library in their distribution.

At application startup, the listener extracts the ApplicationContext from the ServletContext and registers it on a ContextProvider. The provider is statically accessible to the application and can make available the ApplicationContext as follows:

ApplicationContext ctx = ContextProvider.get()

The application can then access all the information and notification mechanisms that are directly or indirectly provided by SmartGears.

gCube-aware applications that use Maven can specify their dependencies to Smartgears as shown in the Appendices.

Authorization

Authorization is transparent for all the Smartgears apps. The TOKEN is automatically read and resolved on every call. In case the developer needs to know the current context of the call or the client that is trying to access the webapp, two ThreadLocal variables are set in the current Thread:

  • CurrentContext;
  • AuthorizationProvider.

The ScopeProvider.instance.get() method returns a String representing the current context.

The AuthorizationProvider.instance.get() method returns a Caller object containing the identifier and roles of the caller.

Accounting

Calls received by a Smartgears enable service are automatically accounted. The method name used is extracted from the PathInfo (in case of REST service) or from the client. Another way to set internally a custom method name is to set the InnerMethodName thread local.

InnerMethodName.instance.set("methodnameToAccount")


Intialization

The smartgears framwork allows services to make some work at initialization-time (e.g. search for resources, register to a topic etc.). To enable this functionality is sufficent to create a class that implements the ApplicationManager class.

..
import org.gcube.smartgears.ApplicationManager;
..
 
public class MyAppManager implements ApplicationManager {
 
	private static Logger logger = LoggerFactory.getLogger(MyAppManager.class);
 
	ApplicationContext ctx = ContextProvider.get();
 
	@Override
	public void onInit() {
	   //do something on init
	}
 
	@Override
	public void onShutdown() {
	   //do something on shutdown
	}
}

The last thing to do is to declare the servlet implementation class as ManagedBy the MyAppManager class.

..
import org.gcube.smartgears.annotations.ManagedBy;
..
@WebService(portName = "TestPort",
serviceName = "testinterface",
targetNamespace = "http://gcube-system.org/test",
endpointInterface = "org.gcube.test.ServiceInterface")
@ManagedBy(MyAppManager.class)
public class FactoryTest implements ServiceInterface {
 
..
 
}

The implemented ApplicationManager keep the state per context. The ApllicationManager related to current context can be recovered on the managed class as follow:

..
import org.gcube.smartgears.ApplicationManagerProvider;
 
..
MyAppManager appManager = (MyAppManager)ApplicationManagerProvider.get();
..

Appendices

Container Descriptor

SmartGears manages containers according to the instructions found in a $GHN_HOME/container.xml descriptor. We can illustrate the structure of this descriptor by example, commenting out elements that are optional:

<container mode='online'>
 
     <hostname>acme.org</hostname>
    <port>8081</port>  
 
    <infrastructure>gcube</infrastructure>
    <!--<token>tokenContext1</token>-->
    <!--<token>tokenContext2</token>-->
 
    <!--<persistence location="/some/custom/location</persistence" /> //THE VALUE MUST BE A VALID DIRECTORY -->
 
    <site>
       <country>it</country>
       <location>rome</location>
       <latitude>41.9000</latitude>
       <longitude>12.5000</longitude>
    </site>
 
    <!--<property name='prop1' value='val1' />--> 
    <!--<property name='prop2' value='val2' />-->
 
    <!--<publication-frequency>60</publication-frequency>-->
 
</container>

Application Descriptor

SmartGears manages applications that include a WEB-INF/gcube-app.xml descriptor in their distributions. We can illustrate the structure of this descriptor by example, commenting out elements that are optional:

<application mode="online">
 
	<name>lorem</name>
	<group>ipsum</group>
	<version>1.0</version>
 
        <!--<description>Lorem ipsum dolor sit amet...</description>-->
 
        <!--<persistence location="/some/custom/location"</persistence/> //THE VALUE MUST BE A VALID DIRECTORY -->
 
        <!--<exclude>/some/app/url</exclude>-->
        <!--<exclude>/some/other/custom/url</exclude>-->
        <!--<exclude handlers='request-accounting'>/*</exclude>  //excludes accounting handler for all paths in the application --> 
 
</application>

Default Logging Configuration

<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file><GHN_HOME>/ghn.log</file>
    <append>true</append>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}: %msg%n</pattern>
    </encoder>
          <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
              <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
	 <maxHistory>30</maxHistory>
        </rollingPolicy>
  </appender>
 
  <logger name="org.gcube" level="INFO" />
 
  <root level="WARN">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Maven Dependencies

gCube-aware applications that use Maven can resolve their dependencies to SmartGears by adding the following to their POMs:

           <dependencyManagement>
                         <dependencies>
			...
			<dependency>
				<groupId>org.gcube.distribution</groupId>
				<artifactId>maven-smartgears-bom</artifactId>
				<version>LATEST</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			...
		</dependencies>
	</dependencyManagement>
          ...
	<dependencies>
          ...	
	<dependency>
			<groupId>org.gcube.core</groupId>
			<artifactId>common-smartgears-app</artifactId>
		</dependency>
		<dependency>
			<groupId>org.gcube.core</groupId>
			<artifactId>common-smartgears</artifactId>
		</dependency>
                  ….
	</dependencies>

The first dependency is to SmartGears's “Bills of Materia”l (BOM), a POM-only Maven artefact which specifies dependencies to all the SmartGears libraries. By importing it in the dependencyManagement section of their POMs, applications make sure that dependencies to SmartGears libraries:

  • have provided scope, i.e. will not be bundled with the applications;
  • are the latest available versions, those with which the applications will be built and then managed in production.

The version LATEST matches the latest release of the BOM, which is always kept in sync with the latest release of SmartGears. During gCube builds, LATEST is resolved to and replaced with a specific version number, so that the reproducibility of release builds is always guaranteed.

The other two concrete dependencies are to common-smartgears-app and common-smartgears, and rely on versions and scopes defined in the BOM.