-
Notifications
You must be signed in to change notification settings - Fork 12
Step By Step: First Service
In this tutorial, you get an introduction to las2peer development. After this tutorial, you will know the basics of las2peer service development and testing. It does not include information on how to start a las2peer node via the L2pNodeLauncher tool to use it in a 'productive' environment. If you want to (only) learn about this, the tutorial on starting a las2peer network is suggested. Otherwise, we recommend this tutorial as your starting point into las2peer service development.
Please note that this tutorial uses Windows 10 as OS and Eclipse as IDE (version 2020-12). If you use another OS or IDE, some of the steps or screenshots might slightly differ from your experience, but you still should be able to follow this tutorial.
So let's begin. First, we have to checkout the template project from GitHub.
On the project's main GitHub page,
on the right side you can find a "Download ZIP" button. Click this and extract the content to your chosen workspace.
(You can delete the -master
extension from the folder name):
Before importing the project in Eclipse, please make sure, that JavaSE-14 is available in Eclipse (check under Window -> Preferences -> Java -> Installed JREs -> Execution Environments).
Now, open Eclipse and go to File → Import and select Gradle/Existing Gradle Project.
A window opens and you should see the welcome page of the Gradle project import wizard.
After clicking "Next" you should select the project root directory (this is the las2peer-template-project
folder inside your workspace).
After clicking "Next" again, you will see some import options.
Please do not change anything in these options and click "Next" again.
Then in the "Import Preview" you should see the las2peer-template-project
and can click on "Finish".
After importing the project you should see two items in your workspace in Eclipse: las2peer-template-project
and template_project
.
There should not be any error messages showing up, because the required libraries should have been fetched automatically during the import-process.
We continue by changing the default service name according to your desired one.
Please open the gradle.properties
file (in the las2peer-template-project
).
You now see some parameters, which you can adjust to your needs (You could just leave everything as it is,
of course. Then you will create a service called templateService
with its main class TemplateService
).
In this example, we changed the values to some alternative ones, just so you can see where else you have to adjust the
projects settings if you change them. The alternative values are:
core.version=1.1.1
service.name=i5.las2peer.services.myNewService
service.class=MyNewServiceMainClass
service.version=0.1.0
Now, we have to adjust our project's structure accordingly. Therefore, please rename the two packages (inside template_project
) according to the value you gave service.name
(right-click on it → Refactor → Rename). A warning should pop up when you rename the second package, but you can just click Continue
.
Next, please change the name of the TemplateService.java
file to the value you gave your service.class
(your service name).
Then, please change the name of the service's configuration file in the ./etc
folder (in las2peer-template-project
) to the canonical classname of your service with a .properties
ending. In the template, rename the file ./etc/i5.las2peer.services.servicePackage.TemplateService.properties
accordingly.
In our case, we rename it to ./etc/i5.las2peer.services.myNewService.MyNewServiceMainClass.properties
.
Now we can also change the name of our project.
Therefore, first update the settings.gradle
(in las2peer-template-project
) and replace the name template_project
accordingly to the name of your service.
In our case, we will set it to my_new_service
.
include('my_new_service')
Now we can rename the template_project
folder and also set it to the same name, here it would be my_new_service
again.
Please note: When doing this in Eclipse, this will only update the project name in the .project
file.
Make sure that you also rename the folder itself (in a file explorer).
After that, refresh the Gradle project in Eclipse (right-click on the las2peer-template-project
in Eclipse → Gradle → Refresh Gradle Project). After this, you should see the two entries las2peer-template-project
and my_new_service
in Eclipse.
The name of the root folder las2peer-template-project
can also be changed if wanted.
The following screenshot shows the renaming, left is the imported project and right the project with the names adjusted to the values above:
The start script bin/start_network.[sh|bat]
will be generated automatically according to the information given in the gradle.properties
file.
Remark: We will not discuss all the details of a RESTful Web Service here. We just give you the minimal knowledge needed to run your first service. There exist a lot of tutorials that cover RESTful development in more detail, and we strongly encourage you to first gain a bit of knowledge of how RESTful architectures look like before continuing with this tutorial, since it focuses more on the technical part.
Let's take a look at our main service class (MyNewServiceMainClass.java
in our example). It starts with the package declaration and then there are some imports. Nothing fancy here, just plain old Java stuff. So next comes the class definition.
You might notice some annotations, such as @ServicePath
, which might not be intuitive. With this argument, we explain the WebConnector
(or more specifically the RESTMapper
, but this is not important at the moment) at which path our service
can be reached via the HTTP / HTTPS protocol. A las2peer Connector realizes the communication from a las2peer node to the outside.
The WebConnector
is the Connector implementation used for RESTful access via HTTP/HTTPS. In our example we use the path template
.
REST services should extend the RESTService
class to be invocable from the WebConnector. There also exist other services extending the Service
class, which do not provide a RESTful interface.
Let's take a look at the class' content. It contains two methods.
The first method is called getTemplate()
. Notice the @GET
annotation and again the @Path
. This means that the method can be reached via HTTP GET
at the path template/get
(main class path and then the path of the individual method).
So what does it do? It creates a String and returns it. Ok, that's clear. The new part is here:
UserAgent userAgent = (UserAgent) Context.getCurrent().getMainAgent();
While it might be somehow clear what the result of this might be, let's try to understand what exactly is happening.
In las2peer, every acting entity is an agent. So a user that calls a service's method is also an agent. So we tell the service to get the active (= calling) agent, then we cast it to a UserAgent
(since, as previously said, all acting entities are agents, so the caller could also have been for example a ServiceAgent
, which has no login name) to be able to get his login name.
The next method again has two annotations, @Post
and @Path
. The path contains a value in curly brackets. This value is used in the methods' declaration in the annotation @PathParam("input")
. Here you can see one way of passing values to a las2peer service via HTTP / HTTPS. In this case, we can address the method via template/post/
and then add the value we want to pass to it, so for example template/post/aValue
. The method itself just returns a String telling you what you have passed.
Each las2peer service can define its own configuration in an external configuration file. All of these files are expected to be in the ./etc
folder. The file name of a service's configuration file must be the canonical service class name followed by a .properties
suffix. In our example, such a configuration file would be expected at ./etc/i5.las2peer.services.myNewService.MyNewServiceMainClass.properties
. In the example below, you will find a sample configuration, as also contained in the bundled service config. Syntax is simple: one parameter per line, key=value
.
templateProperty="Insert your properties here"
Parameter values in such a config files are then accessible as ready-to-use variables within Java code. By defining field variables for the parameters in your Java code and adding setFieldValues()
to the constructor of your services main class, las2peer will read the configuration file and set the values as defined there. Additionally, the annotation @ManualDeployment
has to be added before defining your service class to enable the use of configuration files.
private String templateProperty;
Now that we understand what our service looks like, let us take a look at the ServiceTest.java
which uses JUnit to test our service.
Usually, las2peer test cases try to simulate a service call. This means that you need the following components setup before running your test:
- a las2peer node
- your service running at this node
- a connector running at this node that supports your chosen communication method
- a user agent that makes the service calls
These are variables declared at the beginning of our test class:
node
connector
logStream
testAgent
testPass
mainPath
Node and connector are self-explanatory and the log stream is used to log all upcoming connector events and print them after a test case. The test agent is the user agent used for calling the methods and is unlocked by a pass-phrase. In this case, we use the agent adam
from the so called MockAgentFactory
that ships with las2peer for exactly those testing cases. The main path is the service path we defined at the beginning of our main service class.
Next, we have the startServer
and shutdownServer
methods. Since those are annotated with @Before
/ @After
, they are executed once before the first test and after the last one. Their implementation is a pretty straightforward las2peer node setup / shutdown and will not be discussed in detail here.
Now we focus on the actual tests. The class contains two tests for the two example methods of our service. We will explain the first one in detail. Every test first sets up a so called 'MiniClient', of which you can think as your 'simulated Web browser', so it is capable of communicating via the HTTP protocol. We then set the connector endpoint and continue by setting a login of the test agent we predefined earlier. Now comes the interesting part. With
ClientResponse result = c.sendRequest("GET", mainPath + "get", "");
we actually make the service call. It is stored in the variable result
for later checks. The method takes three parameters. The first one is the HTTP method, in our example it is "GET"
. Next comes the path and the last one are parameters, which we don't use here.
After the call, we can check the result for expected values. In this case, we check, if the HTTP response code is 200 and if the returned result contains the string adam
(since this should be the desired behavior of the method, as discussed in the previous section The Service Class). Finally, we print out the result again for later reference. It will be stored in our test report. Please note that most of the test case is surrounded by a try-catch block that is responsible for catching all unexpected behavior. In this case, the tests will fail and you will get information on the failure in your test report.
So finally you made it through to the part where you can actually run and test your service :-).
In Eclipse, open the "Gradle Tasks" view (if not already visible you can open it with Window → Show View → Other → Gradle → Gradle Tasks).
In the tasks view you find the build task under las2peer-template-project → my_new_service → build.
Double-click on the build task to run it. If you have done everything correctly, the script should run without an error and you should be able to find new log
, service
and export
folders in your project.
In the build
folder there should also exist a folder reports
where you can find the reports from your tests.
Alternatively, execute the following command on your shell (assuming you have gradle
and java
executables on the path):
gradle clean build
This concludes the first steps tutorial. You now should have a very basic idea about las2peer RESTful service development. Although we have not discussed every part of your project and how to actually use the compiled service, you know enough to start writing your service code and test it accordingly. The next tutorial on starting a las2peer network focuses more on how the structure of a las2peer node looks like and gives information on how a las2peer instance is set up (what to put in which folder and such things). If you intend to share any of the services you created with the Open Source community, then be sure to properly license your code, following our guidelines. You might also want to consider having your service host its own developer documentation with Swagger, following our guidelines.