Scout/Concepts/Communication
Scout |
Wiki Home |
Website |
Download • Git |
Community |
Forums • Blog • Twitter • G+ |
Bugzilla |
Bugzilla |
Client and backend communicate using the HTTP protocol or its extension HTTPS, providing Transport Layer Security (TLS). Client requests are sent as HTTP POST requests, carrying SOAP messages as payload.
Although the interface looks like a standard web service, there is no WSDL interface description for internal Scout services. The interface is extracted directly out of implementing classes using Java serialization. The serialized service invocation and its result are written into the SOAP message’s body. The SOAP body is enriched with additional plain-text elements, since the serialized data looks obscured for external parties being involved in the transportation chain (e.g. content filters). This communication scheme is called mixed-mode.
Scout provides support out of the box for switching to an exclusive XML-based communication scheme. However performance will be impacted by verbose messages exchanged between client and backend and the interfaces are still not described by WSDL documents (actually the data is just serialized into XML). Performance will decrease with a factor of about 3 to 5 times.
Additionally Scout makes use of HTTP sessions for performance reasons. Using the session notion contradicts common web service principles, demanding for stateless service implementations.
Several switches exist to control how a Scout client handles Proxy settings.
Contents
Service Tunnel
Scout client - server communication is designed so it can be used completely transparent and easy. Although the communication is based on SOAP it is not necessary to define a WSDL for each service and create their stubs on the client. Instead those remote services are accessible through the OSGi service registry like any other (client) service. The key of that simple but powerful concept is called "dynamic proxy".
The steps to create such a remote service are as follows:
- Create a service interface in the shared plugin
- Implement the service in the server plugin
- Register the implementation as scout server service in the server plugin
- Register the service interface as scout client service proxy in the client plugin
Request Response Roundtrip
At the core of the scout client proxy service registry a new interface of the desired type is created as a reflection java proxy with a handler that delegates all invocations to that interface to the HttpServiceTunnel: ServiceTunnelInvocationHandler.invoke()
--> HttpServiceTunnel.tunnelOnline()
.
The HttpServiceTunnel wraps the invocation as HttpServletRequest and sends it via IServiceTunnelContentHandler
to the server servlet with path /process. In the server the path /process is mapped in the plugin.xml
to the ServiceTunnelServlet.
Before the call is received by the servlet it has to pass the active servlet filters, one after another. These filters are also defined in the plugin.xml
of the server and typically used for authentication checks. The BasicSecurityFilter
for example enforces a valid username/password using HTTP BASIC Auth.
Finally the ServiceTunnelServlet is receiving the request. At that moment the code is running inside a JAAS security context due to the SecurityFilter. Before delegating the call to the actual service the ServiceTunnelServlet
deserializes the request using the same IServiceTunnelContentHandler
as the client, creates and loads the ServerSession
and also creates a ServerJob
, which opens a transaction for the incoming request. That ServerJob
delegates the call to the ITransactionDelegate
, which invokes the actual service.
When the processing is finished the transaction will be committed and the response serialized by the IServiceTunnelContentHandler
and sent back to the client.
Input/Output Validation
By default there is no input and output validation of incoming and outgoing remote service calls.
In order to activate central input/output validation, create and use a subclass of ServiceTunnelServlet
and override runServerJobTransactionWithDelegate()
.
There use a subclass of DefaultTransactionDelegate
with implemented methods filterInput()
and filterOutput()
.
The easiest way to implement is by calling new DefaultValidator().validate()
;
The DefaultValidator
validates all arguments using a deep-traversal check. Form data classes (subclasses of AbstractFormData
) are checked with the delegate DefaultFormDataValidator
.
This is very useful since the eclipse scout sdk writes all ui model properties relevant for validation automatically to the form data.
For example a StringField
in a form defining a maxLength of 200 by
public class LastName extends AbstractStringField { ... protected int getConfiguredMaxLength(){ return 200; } }
will result in a form data field
public class LastName extends AbstractValueFieldData<String> { ... public static final HashMap<String,Object> validationRules=new HashMap<String,Object>(); static{ validationRules.put("maxLength",200); } }
That way you define your business rules exactly once and they are automatically checked at the central input validation on the server, since the shared form data classes are used on client and server.
For more details see ValidationRule
, ValidationStrategy
, IValidator
.
Message Structure
Base64 encoded Serialized objects
The request parameters as well as the response data can be transmitted in different customizable formats (contents of the <data>...</data> tags). Scout provides support out of the box for switching to an exclusive XML-based communication scheme.
Request Message
The request SOAP message consists of:
- Service reference, operation, version, formatting, language
- Service arguments
- Information like timestamp, TCP/IP origin, varia (xsd:any)
Mime-type: application/soap+xml <?xml version="1.0" encoding="UTF-16"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <request version="3.0.0" format="de_CH" language="de_CH" service="com.bsiag.scout.shared.services.common.ping.IPingService" operation="ping"/> <data>…</data> <info ts="20080715114301917" origin="192.168.1.105">…</info> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Response Message
The response SOAP message consists of:
- Service invocation status, maybe exception type
- Service response data
- Information like timestamp, TCP/IP origin, varia (xsd:any)
Example with Status: „OK“
Mime-type: application/soap+xml <?xml version="1.0" encoding="UTF-16"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <response status="OK" type="String"/> <data>…</data> <info ts="20080715114301917" origin="192.168.3.2">…</info> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Example with Status „ERROR“
Mime-type: application/soap+xml <?xml version="1.0" encoding="UTF-16"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <response status="ERROR"> <exception type="SecurityException">Access denied</exception> </response> <data>…</data> <info ts="20080715114301917" origin="192.168.3.2">…</info> </SOAP-ENV:Body> </SOAP-ENV:Envelope>