|
## [Home](https://git.opendfki.de/reuschling/ragnarok/-/wikis/Home) | [Documentation](https://git.opendfki.de/reuschling/ragnarok/-/wikis/Documentation) | [People](https://git.opendfki.de/reuschling/ragnarok/-/wikis/People)
|
|
## [Home](https://git.opendfki.de/reuschling/sparkling/-/wikis/Home) | [Documentation](https://git.opendfki.de/reuschling/sparkling/-/wikis/Documentation) | [People](https://git.opendfki.de/reuschling/sparkling/-/wikis/People)
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
... | @@ -6,5 +6,107 @@ |
... | @@ -6,5 +6,107 @@ |
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
# TODO
|
|
# Creating a server
|
|
BlaBlabla |
|
We shown how to create and start a web service on our [welcome page](Home). Sparkling analyzes the methods of the given handler object and uses Spark to add __both a GET and a POST__ endpoint for each method, together with parameter and return value conversion. Further, it __creates a documentation website__ for the handler object, listing all service methods available together with a generated Java interface for Java client instance creation. [Look here](GeneratedDocExample) for an example of a generated documentation website.
|
|
|
|
|
|
|
|
You have some possibilities to control server creation with Sparkling:
|
|
|
|
* __Pick the methods__ that should be available via the server:
|
|
|
|
1. `Sparkling.startServer(..)` gives a parameter where you can specify the names of the methods that should not be used.
|
|
|
|
2. Annotate a method with `@Skip4Service`.
|
|
|
|
* Add default values to your method parameters with `@DefaultValue("myValue")` in order to omit them at request time.
|
|
|
|
* Add __several handler objects__ to the server with `Sparkling.addHandler2Server(..)`. You can specify a subpath for each handler object. The only difference to `Sparkling.startServer(..)` it that `Sparkling.startServer(..)` specifies the port of the server also.
|
|
|
|
* Make cleanups at __server shutdown__, when you e.g. have to close some database connections, with `Sparkling.addShutdownRoutine(Runnable runnable)`.
|
|
|
|
* __Suppress documentation__ creation with `createDocumentation=false` as parameter of `Sparkling.addHandler2Server(..)` and `Sparkling.startServer(..)`.
|
|
|
|
* Log __invocation statistics__ with `logInvocationStatsEveryNCalls=N`. The server will log every `N` method invocations the counts which method was called how often since the last server (re)start.
|
|
|
|
* You can __suppress__ that values of specified __parameters will be logged__ by Sparkling. Sometimes, in the case of an error, Sparkling will log parameter values for debugging reasons. If you e.g. for some reason have a password parameter, you don't want the passwords to appear in the logs. Suppress the logging by annotating the parameter with `@HideValueLogs` inside the handler method code.
|
|
|
|
|
|
|
|
# Spark as underlying micro framework
|
|
|
|
Since Sparkling simply connects the Spark server to the handler methods with [Spark](http://sparkjava.com/), you can use __all Spark functionality__ furthermore. Nothing special. Add new requests before or after you add a handler with Sparkling, deal with https, and plenty of more. Look into the fantastic [Spark documentation](http://sparkjava.com/documentation) for all possibilities.
|
|
|
|
|
|
|
|
# Data conversion
|
|
|
|
When you create the service http calls on your own, you have to deal with how Sparkling converts the parameter and return values. In general, primitive types will be offered inside the service API as-is (Strings, Numbers and Boolean). All other classes that are used as parameter or return values will be converted to and from JSON.
|
|
|
|
|
|
|
|
An example call would look like this:
|
|
|
|
|
|
|
|
GET http://localhost:8080/myservice/mymethod?parameter=great
|
|
|
|
|
|
|
|
The following capabilities exist:
|
|
|
|
|
|
|
|
* __Primitive types__ (numbers, strings and boolean) will be transported as-is (simple strings)
|
|
|
|
|
|
|
|
|
|
|
|
GET http://localhost:8080/my-service/mymethod?simpleNumber=23
|
|
|
|
GET http://localhost:8080/my-service/mymethod?simpleBoolean=true
|
|
|
|
GET http://localhost:8080/my-service/mymethod?simpleString=a%20string%20with%20spaces
|
|
|
|
|
|
|
|
* __Complex types__ (all others) will be converted into JSON representation
|
|
|
|
|
|
|
|
GET http://localhost:8080/my-service/mymethod?complexParam={"number":23,"string":"hello"}
|
|
|
|
|
|
|
|
* __Arrays of primitive and complex types__ are permitted
|
|
|
|
|
|
|
|
* __null String values__ are represented with the zero byte (ASCII 0 / NUL). Specify it with Url encoding: '?parameterNull=%00'
|
|
|
|
|
|
|
|
GET http://localhost:8080/my-service/mymethod?parameterNull=%00
|
|
|
|
|
|
|
|
* __POST or GET__ is possible to make the call
|
|
|
|
* Url parameters are used for GET
|
|
|
|
* For POST, the parameters can be sent either as form data or as multipart 'text/plain' parts. Encoding is __always UTF-8__.
|
|
|
|
|
|
|
|
* __Big data transfers__ (e.g. file uploads and downloads) are supported by handler InputStream parameters and return types.
|
|
|
|
* Stream HTTP return values are of type `application/octet-stream`.
|
|
|
|
* Stream parameters are only supported for POST multipart requests. Stream parts are of type `application/octet-stream`.
|
|
|
|
|
|
|
|
* You __can omit parameters in a request__. In this case, the default value of the parameter type is used. You can overwrite this behavior by setting your __own parameter default values__ with the `@DefaultValue` annotation in the handler code. Default values are in transport representation, i.e. primitives or Json for complex types:
|
|
|
|
```java
|
|
|
|
public void myMethod( @DefaultValue("defaultVal") String stringParam, @DefaultValue("23") int numParam)
|
|
|
|
```
|
|
|
|
User specified default values will also be shown inside the generated documentation.
|
|
|
|
The type specific default values are:
|
|
|
|
* For numbers, the default value is __0__ (e.g. 0 for int or Integer, 0.0 for double and Double). Primitive and complex numbers are handled the same way.
|
|
|
|
* For booleans, the default value is __false__.
|
|
|
|
* For Strings, the default value is the __empty String ""__.
|
|
|
|
* For complex types, the default value is __null__.
|
|
|
|
|
|
|
|
|
|
|
|
* If you have values of classes with an inheritance and you specify an interface or an upper class inside the method declaration, the default JSON conversion will fail because there is no dedicated type information inside the generated JSON Strings. For this case, you can annotate the parameter with `@Polymorph`. Doing this, we use [JSON-IO](https://github.com/jdereg/json-io) as serializer, that as of our knowledge is the only JSON serializer that is able to deal with class hierarchies at (de)serialization time. The specific types of the serialized objects will be added to the JSON containers if necessary.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Java method parameter names
|
|
|
|
Sparkling needs to know the parameter names of the handler object methods in order to offer according named parameters for the http GET and POST calls. Since the Java compiler does not provide them per default, we have to take care that Sparkling can get these names at server creation time.
|
|
|
|
|
|
|
|
Since Java version 8 the java compilers offers the command line option `-parameters`. With this flag enabled the compiler will write parameter name metadata into the created bytecode. These names are then available via the reflection API. Take care to enable this flag at compile time of your server.
|
|
|
|
|
|
|
|
__Command line__: `javac -parameters ...`
|
|
|
|
|
|
|
|
__IntelliJ__: Settings => Java Compiler => Additional command line parameters: `-parameters`
|
|
|
|
|
|
|
|
__Maven:__
|
|
|
|
```xml
|
|
|
|
<build>
|
|
|
|
<pluginManagement>
|
|
|
|
<plugins>
|
|
|
|
<plugin>
|
|
|
|
<groupId>org.apache.maven.plugins</groupId>
|
|
|
|
<artifactId>maven-compiler-plugin</artifactId>
|
|
|
|
<version>3.8.1</version>
|
|
|
|
<configuration>
|
|
|
|
<compilerArgs>
|
|
|
|
<arg>-parameters</arg>
|
|
|
|
</compilerArgs>
|
|
|
|
</configuration>
|
|
|
|
</plugin>
|
|
|
|
</plugins>
|
|
|
|
</pluginManagement>
|
|
|
|
</build>
|
|
|
|
```
|
|
|
|
|
|
|
|
In the case you have to work with Java <8 or you don't want or can set the `-parameters` flag for some reason, we offer an annotation `@Named` as alternative. Using this, the parameter name is specified as parameter annotation instead of bytecode metadata. The pro is that you are independent from the compiler flag. The con is that you have to provide the parameter name for each parameter on your own. Use it as follows:
|
|
|
|
|
|
|
|
```java
|
|
|
|
// gives the first parameter the name 'ping'
|
|
|
|
public void myMethod( @Named("ping") String arg0 )
|
|
|
|
```
|
|
|
|
|
|
|
|
Note that if you don't specify anything, Java will name the parameters as `arg0, arg1, ...argN`. The service communication will work with these parameter names also, it looks messy if you have a look on it of course. Nevertheless, if you use the generated java client only, service communication will work as expected. You will only get in contact with the parameter names when you create the http calls on your own. |