Skip to content

Commit b2f0ca3

Browse files
committed
Add Readme
1 parent 8580f20 commit b2f0ca3

File tree

1 file changed

+52
-175
lines changed

1 file changed

+52
-175
lines changed

README.md

Lines changed: 52 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,64 @@
1-
# Spring Boot Starter (template)
2-
3-
A minimal working starter template for a Spring Boot non-web applications using the
4-
Spring [CommandLineRunner](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/CommandLineRunner.html)
5-
interface with a demonstration of Java
6-
annotation-based [Inversion of Control](https://stackoverflow.com/questions/3058/what-is-inversion-of-control)
7-
via [Dependency Injection](https://stackoverflow.com/questions/130794/what-is-dependency-injection).
8-
9-
## Run the app
10-
11-
Checkout the latest code from `main` and run the Maven goal `spring-boot:run`:
12-
13-
```
14-
mvn spring-boot:run
15-
```
16-
17-
## What the app does
18-
19-
This small app just parses a file with a collection of good coding prayers and creates a singleton
20-
instance of an `CodingPrayersMessageService`. This concrete implementation uses the
21-
interface `MessageService`, that comes with only one public method: `String collectMessage()`.
22-
23-
This service is used to demonstrate the IoC principle. We have defined another interface `NewsMedia`
24-
and provide a concrete implementation `DeveloperNews`, that will call the message service to receive
25-
recent news and forward them to the caller.
26-
27-
In the main app code, we just retrieve this Singleton instance or Bean in Spring lingua from the
28-
loaded context and call the news media `getNEws()` method. The collected message is then printed out
29-
to the command line interface:
30-
31-
```
32-
33-
. ____ _ __ _ _
34-
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
35-
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
36-
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
37-
' |____| .__|_| |_|_| |_\__, | / / / /
38-
=========|_|==============|___/=/_/_/_/
39-
:: Spring Boot :: (v2.5.6)
40-
41-
2021-11-18 09:17:37.640 INFO 68052 --- [ main] l.q.s.SpringMinimalTemplateApplication : Starting SpringMinimalTemplateApplication using Java 17.0.1 on imperator.am10.uni-tuebingen.de with PID 68052 (/Users/sven1103/git/spring-boot-starter-template/target/classes started by sven1103 in /Users/sven1103/git/spring-boot-starter-template)
42-
2021-11-18 09:17:37.641 INFO 68052 --- [ main] l.q.s.SpringMinimalTemplateApplication : No active profile set, falling back to default profiles: default
43-
2021-11-18 09:17:38.164 INFO 68052 --- [ main] l.q.s.SpringMinimalTemplateApplication : Started SpringMinimalTemplateApplication in 0.808 seconds (JVM running for 1.489)
44-
####################### Message of the day ##################
45-
Have you written unit tests yet? If not, do it!
46-
##############################################################
47-
1+
# OpenBiS Dropboxes
2+
3+
!!! abstract
4+
After the [Data Scanner](#), data registration in openbis can be automated by dropboxes.
5+
We use Java Dropboxes to move files into OpenBis (see
6+
the [Documentation on Java Dropboxes](https://openbis.readthedocs.io/en/20.10.x/software-developer-documentation/server-side-extensions/dss-dropboxes.html#java-dropboxes))
7+
8+
## Context
9+
10+
```mermaid
11+
sequenceDiagram
12+
autonumber
13+
User ->> SFTP Folder : move files
14+
Data Scanner ->> SFTP Folder : is new data present?
15+
SFTP Folder ->> Data Scanner : Yes
16+
Data Scanner ->> Dropbox Incoming : move files
17+
Data Scanner ->> Dropbox Incoming : create marker file
18+
Dropbox ->> Dropbox Incoming : Is marker file present?
19+
Dropbox Incoming ->> Dropbox : Yes
20+
Dropbox ->> OpenBiS : Register data
4821
```
4922

50-
## Realisation of IoC and DPI
51-
52-
The messages collection is stored in a simple text file `messages.txt`, that is provided with the
53-
apps `resources`. Just go ahead and change the content of the file and run the app!
54-
55-
<img width="308" alt="grafik" src="https://user-images.githubusercontent.com/9976560/142380084-d01081d2-79fb-4ff3-acc5-3140dca38f6a.png">
56-
57-
58-
So how does the app know where to find this file and **load the messages content**?
59-
60-
We have configured it as a **external property** in a file `application.properties` and load the
61-
configuration on application startup! Cool eh?
62-
63-
<img width="381" alt="grafik" src="https://user-images.githubusercontent.com/9976560/142376871-5bee068f-208c-4af0-a35b-9442ee498789.png">
6423

65-
This is how the file content looks like:
24+
### Dropbox Process
6625

67-
```
68-
messages.file=messages.txt
69-
```
70-
71-
So how do we access the value of the `messages.file` property in our application with Spring?
72-
73-
Have a look in the class `AppConfig`, there the magic happens:
26+
The dropbox processes the data before moving it into OpenBiS. A successful processing is shown
27+
below.
7428

75-
```groovy
76-
@Configuration
77-
@PropertySource("application.properties")
78-
class AppConfig {
29+
The process is triggered when a marker filed called `MARKER_is_finished_<dirname>` with `<dirname>` being the folder to be registered, is created.
7930

80-
@Value('${messages.file}')
81-
public String messagesFile
31+
``` mermaid
32+
sequenceDiagram
33+
autonumber
34+
IncomingFolder ->> Dropbox: Folder and Markerfile exist
35+
Dropbox ->> IncomingFolder: Read provenance.json
36+
Dropbox ->> Dropbox: Parse measurement ID
37+
Dropbox ->> OpenBiS DSS: Get measurement sample
38+
OpenBiS DSS ->> Dropbox: Give measurement sample
39+
Dropbox ->> OpenBiS DSS: Has measurement datasets?
40+
OpenBiS DSS ->> Dropbox: No
41+
Dropbox ->> Dropbox: Parse measurement properties
42+
Dropbox ->> OpenBiS DSS: Create dataset
43+
Dropbox ->> OpenBiS DSS: Send files to dataset
8244
```
8345

84-
We define the property source, which is the file `application.properties` that is provided in the
85-
resource folder of the app and available to the classpath. We also tell with the
86-
annotation `@Configuration` Spring, hey this is a class that holds app configuration data!
46+
### Dropbox Configuration
8747

88-
With the annotation `@Value('${messages.file}')` we tell Spring, which property's value should be
89-
injected. Here we make use of field injection, other types of injection like method and constructor
90-
injection are also possible.
48+
The dropbox configuration can be found
49+
at `...` on the OpenBiS instance. Each folder within this directory creates a dropbox.
9150

92-
So how is the concrete implementation of the `MessageService` presented to Spring? We can use
93-
the `@Bean` annotation here, to tell Spring: _hey, this is sth you must load on startup and provide
94-
to the context_.
51+
Within each folder exists a directory `lib` and a file `plugin.properties`. The `lib` folder is
52+
where you place your dropbox `jar` file. The `plugin.properties` is where you configure your
53+
dropbox.
9554

96-
```java
97-
@Configuration
98-
@PropertySource("application.properties")
99-
class AppConfig {
100-
101-
....
102-
103-
@Bean
104-
MessageService messageService() {
105-
return new CodingPrayersMessageService(messagesFile)
106-
}
55+
```properties title="plugin.properties" linenums="1"
56+
incoming-dir=...
57+
incoming-data-completeness-condition=marker-file
58+
top-level-data-set-handler=ch.systemsx.cisd.etlserver.registrator.api.v2.JavaTopLevelDataSetHandlerV2
59+
program-class=life.qbic.registration.openbis.OpenBisDropboxETL
60+
storage-processor=ch.systemsx.cisd.etlserver.DefaultStorageProcessor
10761
```
108-
109-
That is all there is, you can now load the bean in your main application code:
110-
111-
```java
112-
@SpringBootApplication
113-
class SpringMinimalTemplateApplication {
114-
115-
static void main(String[] args) {
116-
SpringApplication.run(SpringMinimalTemplateApplication, args)
117-
// load the annotation context
118-
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class)
119-
// get the service bean
120-
MessageService service = context.getBean("messageService", MessageService.class)
121-
// collect the message and praise the magic
122-
println service.collectMessage()
123-
124-
```
125-
126-
### Inversion of Control
127-
128-
<img width="990" alt="grafik" src="https://user-images.githubusercontent.com/9976560/144576610-4dd4aa0a-1b58-4832-aaac-0bb70757a9a1.png">
129-
130-
You might have already spotted the interface `NewsMedia` and its implementing class `DeveloperNews`
131-
in the app's source code. Here you can see an example for the magic of inversion of control.
132-
133-
The `NewsMedia` interface is just an abstraction that we will later use, because we don't care about
134-
the actual implementation details. By this, we also do not create any dependencies to concrete
135-
implementation details but on actual behaviour. Concrete implementations can then later be exchanged
136-
without causing any breaking changes in the client code base.
137-
138-
The interface has only one method: `String getNews()`. Now let's have a closer look into the
139-
class `DeveloperNews` that implements this interface:
140-
141-
```java
142-
class DeveloperNews implements NewsMedia{
143-
144-
private MessageService service
145-
146-
DeveloperNews(MessageService service) {
147-
this.service = service
148-
}
149-
150-
@Override
151-
String getNews() {
152-
return service.collectMessage()
153-
}
154-
}
155-
```
156-
157-
When you check the constructor signature, you see that this method has only one argument, which is a
158-
reference to an object of type `MessageService`. And when the `getNews()` method is called by the
159-
client, the class delegates this request to the message service. Since we have stored the reference
160-
in a private field, that is super easy, we known how to call the service.
161-
162-
So why is this inversion of control?
163-
164-
Because the `DeveloperNews` class does not manage the instantiation of a concrete message service.
165-
The configuration happened outside of the class, therefore the DeveloperNews class has no direct
166-
control over the instantiation. If it had, it would look like this:
167-
168-
```java
169-
DeveloperNews(String filePathToMessages) {
170-
this.service = new CodingPrayersMessageService(filePathToMessages)
171-
}
172-
```
173-
174-
That doesn't look good, does it? In order to create an instance of a message service, we would need
175-
to know the conrete implementation and its required properties (here it is the file path to
176-
the `messages.txt`). So the `DeveloperNews` class has the control over the message service.
177-
178-
Instead, we would like to not take care about these details, so we invert the control and inject the
179-
dependency via the constructor.
180-
181-
Please find more in depth documentation on the
182-
official [Spring website](https://spring.io/projects/spring-framework).
183-
184-
185-
186-
187-
62+
!!! info
63+
Ususally you only need to adapt the `incoming-dir` and `program-class` when setting up a new dropbox.
64+
For more configuration options please see the [OpenBiS documentation](https://openbis.readthedocs.io/en/20.10.x/software-developer-documentation/server-side-extensions/dss-dropboxes.html#configuration).

0 commit comments

Comments
 (0)