-
Notifications
You must be signed in to change notification settings - Fork 4
web
Classes, interfaces, annotations and extensions in this bundle are used to expose application functionality over HTTP.
-
Routes - match HTTP requests to application actions. Routes can be chained, e.g. a root route can deleage to an object route, which can delegate
to another object route or to an extension route.
- Root routes - Use HTTP method and path pattern for matching.
- Object routes - Use context object type, HTTP method, and path pattern for matching.
- Extension routes - Similar to object routes but use extension string instead of pattern for matching.
- RoutingServlet - dispatches requests to root routes loaded from services and extensions by ExtensionManager
- WebContext - instances of web context or its subtypes are passed to route.execute() method.
- ObjectPathResolver - resolves object path, is used to construct HTTP references.
- UIPart - contribution to a particular object type UI.
- HTML Factory - declares HTML factory accessible by adapting context to HTMLFactory. The factory is used to build Web UI.
- Object Path Resolver - extension point for registering object path resolvers.
- Route - extension points for registering routes.
- UI Part - registers UI parts for a particular class.
Examples are taken from the Server and Examples repository.
Declaration in plugin.xml:
<extension point="org.eclipse.equinox.http.registry.servlets">
<servlet
alias="/router"
class="org.nasdanika.web.RoutingServlet">
<init-param
name="json-pretty-print"
value="true">
</init-param>
</servlet>
</extension>
-
jsonPrettyPrint
-true
value causes JSON output to be indented. -
adapter-service-filter
- service filter for adapter services -
route-service-filter
- service filter for route services -
ui-part-service-filter
- service filter for UI part services -
html-factory
- Name of HTML factory extension to use -
default-access-decision
-deny
sets default access decision toDENY
,ALLOW
otherwise
Routes to AppRoute which implements Route. Declaration in plugin.xml:
<extension point="org.nasdanika.web.route">
<root-route
class="org.nasdanika.examples.bank.app.AppRoute"
method="GET"
pattern="app.html">
</root-route>
</extension>
credit-cards-cdo-transaction-context-provider.xml component provides a root route service which opens CDO Transaction and uses object routes for navigating to repository objects:
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.nasdanika.examples.bank.app">
<implementation class="org.nasdanika.cdo.web.CDOViewContextAutocloseRouteComponent"/>
<property name="pattern" type="String" value="nasdanika(\..+)?(/.+)?"/>
<property name="method" type="String" value="GET"/>
<service>
<provide interface="org.nasdanika.web.Route"/>
</service>
<reference
bind="setContextProvider"
cardinality="1..1"
interface="org.nasdanika.cdo.CDOTransactionContextProvider"
name="CDOTransactionContextProvider"
policy="static"
unbind="clearContextProvider"/>
<property name="type" type="String" value="root"/>
</scr:component>
If pattern
property contains ${bundleId}
token(s), this token is expanded to bundle id. This allows avoid route conflicts in situations when
component routes do not serve application landing pages, but are referenced from such pages. In this case the landing page component can lookup
bundles to be referenced by symbolic name and version using BundleContext.getBundles()
method and generate links to routes exposed by bundle's components.
This kind of assembly of a web application from loosely coupled components is similar and complementary to the UI parts approach.
Declaration in plugin.xml:
<object-route
class="org.nasdanika.cdo.web.routes.CDOTransactionRoute"
method="*"
target="org.eclipse.emf.cdo.transaction.CDOTransaction">
</object-route>
Routes are matched indirectly when WebContext.getAction(Object target, int pathOffset)
method is invoked.
EOperations can be annotated with org.nasdanika.cdo.web:route
and org.nasdanika.cdo.web:home-route
to instruct the
framework to route requests to annotated operations. These annotations support the following details:
-
action
- security action for authorization check, defaults to HTTP method name. -
qualifier
- sequrity qualifier for authorization check, defaults to operatin name. -
method
- a comma separated list of HTTP methods to match, matches any method if omitted. -
path
- path to match, can contain path parameters in {}, e.g.statement/{year}/{month}
. Path takes precedence overpattern
-
pattern
- regex pattern to match request path. Not applicable to the home route annotation. If omitted, path length shall be 1 and equal to the operation name. -
produces
- response content type. Optional. -
consumes
- request content type. Optional, used to match request to method.
Home route matches the object path with .html
extension, e.g. L3.html
.
-
org.nasdanika.cdo:context-parameter
- argument is computed by adapting the context -
org.nasdanika.cdo:service-parameter
- argument is computed by looking up an OSGi service with parameter's type, an optionalfilter
data entry can be used to specify service filter. -
org.nasdanika.cdo:query-parameter
- argument is taken from a query parameter(s) with the name taken fromname
data entry. If there is no such query parameter, argument value is taken fromdefaultValue
annotation data entry. -
org.nasdanika.cdo:path-parameter
- argument is taken from a named path segment with the name taken fromname
data entry. If there is no such path segment, argument value is taken fromdefaultValue
annotation data entry. -
org.nasdanika.cdo:cookie-parameter
- argument is taken from a request cookies(s). An optionalname
data entry can be used to filter cookies by name.
Declaration in plugin.xml:
<extension
point="org.nasdanika.web.html_factory">
<default_html_factory>
<stylesheet>/bootstrap/css/bootstrap.min.css</stylesheet>
<stylesheet>
/bootstrap/css/bootstrap-theme.min.css
</stylesheet>
<script>
/js/jquery-2.1.0.min.js
</script>
<script>
/js/underscore-min.js
</script>
<script>/js/backbone-min.js</script>
<script>/bootstrap/js/bootstrap.min.js</script>
<script>
/js/require.js
</script>
</default_html_factory>
</extension>
Accessing by adapting context:
context.adapt(HTMLFactory.class)
Extension in plugin.xml:
<resolver
class="org.nasdanika.cdo.web.objectpathresolvers.CDOResourcePathResolver"
target="org.eclipse.emf.cdo.eresource.CDOResource">
</resolver>
Implementation - CDOResourcePathResolver:
public class CDOResourcePathResolver implements ObjectPathResolver<CDOResource> {
@Override
public String resolve(CDOResource obj, ObjectPathResolver<Object> master, Context context) throws Exception {
CDOView view = obj.cdoView();
if (view==null) {
return null;
}
String viewPath = master.resolve(view, null, context);
if (viewPath==null) {
return null;
}
return viewPath+"/elements"+obj.getPath();
}
}
Indirect use by invoking getObjectPath()
in CDOViewToHTMLRendererConverter:
for (CDOResourceNode e: source.getElements()) {
String pe = context.getPath()[0];
int didx = pe.lastIndexOf('.');
if (didx!=-1) {
pe = pe.substring(0, didx);
}
if (context instanceof HttpContext) {
elements.add(htmlFactory.routeLink(null, "/"+((HttpContext) context).getObjectPath(e)+".html", e.getName()).toString()); // TODO - escape names
}
}
Declaration in plugin.xml:
<extension point="org.nasdanika.web.ui_part">
<ui_part
category="tabs"
class="org.nasdanika.examples.bank.app.ProtectedActionsUIPart"
target="org.eclipse.emf.ecore.EClass">
</ui_part>
</extension>
public class ProtectedActionsUIPart implements UIPart<HttpContext, NamedItemsContainer<?>> {
@Override
public void create(HttpContext context, NamedItemsContainer<?> out, Map<String, Object> environment) throws Exception {
// if permission
out.item("Protected actions", "Coming soon");
}
}
Collection of UI parts for EClass in EObjectToHTMLRendererConverter.java:
context.buildUICategory("tabs", listsAndContainmentsTabs, null);
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Offers UI Part">
<implementation class="org.nasdanika.examples.bank.app.OffersUIPart"/>
<service>
<provide interface="org.nasdanika.web.html.UIPart"/>
</service>
<property name="target" type="String" value="org.nasdanika.examples.bank.Customer"/>
<property name="category" type="String" value="right-panel"/>
</scr:component>
public class OffersUIPart implements UIPart<HttpContext, Fragment> {
@Override
public void create(HttpContext context, Fragment out, Map<String, Object> environment) throws Exception {
out.content(context.adapt(HTMLFactory.class).alert(Style.SUCCESS, true, "0% APR on balance transfers for 15 months"));
}
}
Collection of ui parts in CustomerImpl:
Fragment rightPanelContent = htmlFactory.fragment();
context.buildUICategory("right-panel", rightPanelContent, null);
if (!rightPanelContent.isEmpty()) {
mainPanel.width(DeviceSize.LARGE, 9);
appPanel.contentPanel(rightPanelContent).width(DeviceSize.LARGE, 3);
}
How it is rendered: