Skip to content

Commit abbc01b

Browse files
committed
add more languages to code blockas
Signed-off-by: Christoph Rueger <[email protected]>
1 parent 3dcc7e9 commit abbc01b

File tree

3 files changed

+77
-57
lines changed

3 files changed

+77
-57
lines changed

_appnotes/interceptors.md

+41-33
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,40 @@ A recurring question on OSGi forums is how to use _interceptors_. The [Spring fr
1010

1111
Let's say we have a function that performs some work. In the following example we need to do some "pre work", "post work", and additionally handle exceptions in similar way:
1212

13-
void doWork() {
14-
preWork();
15-
try {
16-
… do work
17-
postWork();
18-
} catch( Throwable t) {
19-
exceptionWork(t);
20-
throw t;
21-
}
13+
```java
14+
void doWork() {
15+
preWork();
16+
try {
17+
do work
18+
postWork();
19+
} catch( Throwable t) {
20+
exceptionWork(t);
21+
throw t;
2222
}
23-
24-
void doOtherWork() {
25-
preWork();
26-
try {
27-
… do other work
28-
postWork();
29-
} catch( Throwable t) {
30-
exceptionWork(t);
31-
throw t;
32-
}
23+
}
24+
25+
void doOtherWork() {
26+
preWork();
27+
try {
28+
do other work
29+
postWork();
30+
} catch( Throwable t) {
31+
exceptionWork(t);
32+
throw t;
3333
}
34+
}
35+
```
3436

3537
The problem with this approach is that it creates a lot of boiler plate code, and the actual work gets lost. How can we get rid of this noisy and distracting code?
3638

3739
One possible solution is to use Interceptors. With this approach, you add an annotation and now the caller is ensuring that your annotation is correctly interpreted.
3840

39-
@Work(SOME_PARAMETER)
40-
void doWork() {
41-
… do work
42-
}
41+
```java
42+
@Work(SOME_PARAMETER)
43+
void doWork() {
44+
do work
45+
}
46+
```
4347

4448
Voila, boiler plate gone! Problem solved. Or is it?
4549

@@ -76,9 +80,11 @@ However, we're many years further today then when that model was introduced, and
7680

7781
Since Java 8 we now have lambdas! (About 42 years after Smalltalk.) Lambdas are interceptors turned inside out. In the transaction composition problem the interceptor had to do something before it ran our code, then ran our code, and then handle any exceptions and do some post-processing. With lambdas, we can achieve the same model by the method calling the interceptor and passing the function.
7882

79-
void doWork() {
80-
interceptor.doWork( () -> ... working );
81-
}
83+
```java
84+
void doWork() {
85+
interceptor.doWork( () -> ... working );
86+
}
87+
```
8288

8389
That is, instead of typing an annotation above the method, you just use a method with that name and pass it parameters, one of the parameters being the function you want to check.
8490

@@ -90,14 +96,16 @@ An extremely interesting example of this is the work being done on the [Transact
9096

9197
The underlying problem with transactions is that when you get called in a service oriented world it is not always clear how to _compose_ the transactions. I.e. join, reject if on is there, or start. This is a classical problem where you need to do something _before_ and _after_ your actual code. Therefore the transaction control service makes it look like:
9298

93-
@Reference Store<Person> persons;
94-
@Reference TransactionController txc;
99+
```java
100+
@Reference Store<Person> persons;
101+
@Reference TransactionController txc;
95102

96-
public Person findPerson( long id) {
97-
return txc.required( () ->
98-
persons.find( "select * from Person where id=%s", id )
99-
);
100-
}
103+
public Person findPerson( long id) {
104+
return txc.required( () ->
105+
persons.find( "select * from Person where id=%s", id )
106+
);
107+
}
108+
```
101109
102110
Therefore, with the same amount of code (or less) you do not need the magic interceptors.
103111

_qs/410-exercise-service.md

+17-11
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ In OSGi enRoute this means the name of the project should end with `.api` and yo
2525

2626
In this new project, we rename the template API to reflect our semantics. So rename the `com.acme.prime.api` package to `com.acme.prime.upper.api` and the `Prime.java` file to `Upper.java`. Then change the `Upper` class so that we can use it to change a word to upper case:
2727

28-
public interface Upper {
29-
String upper(String input);
30-
}
28+
```java
29+
public interface Upper {
30+
String upper(String input);
31+
}
32+
```
3133

3234
If you have another API in the future, you can then add it to the same project in another package.
3335

@@ -56,20 +58,24 @@ The first thing we need to do is to make sure the Upper Application can see the
5658

5759
Then we change the `UpperApplication` component class. We must add a setter method for the `Upper` service with a `@Reference` annotation, which means we must import `org.osgi.service.component.annotations.Reference`. No we can add the reference to the end of the class (convention is to place references at the end):
5860

59-
public class UpperApplication implements REST {
60-
...
61+
```java
62+
public class UpperApplication implements REST {
63+
...
6164

62-
@Reference
63-
Upper upper;
64-
}
65+
@Reference
66+
Upper upper;
67+
}
68+
```
6569

6670
The `@Reference` annotation creates a dependency on this service; the `UpperApplication` component is not started until the service registry contains an Upper service.
6771

6872
The next step is to use the `upper` instance variable that we've just set in the `getUpper` method (so we must import `com.acme.prime.upper.api.Upper` again).
6973

70-
public String getUpper(String string) {
71-
return upper.upper(string);
72-
}
74+
```java
75+
public String getUpper(String string) {
76+
return upper.upper(string);
77+
}
78+
```
7379

7480
If the OSGi framework is still running, you likely get errors since we now have an unresolved requirement in our code; we're referring to the `com.acme.prime.upper.api` package which is now not provided by anybody.
7581

_tutorial_base/300-api.md

+19-13
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ This section discuss an _API_ project. An API project can be used on the classpa
1717

1818
We want to make a component that evaluates expressions. Though we could start with the implementation, let's do it right and first define the contract. The service contract for now could be an interface:
1919

20-
package com.acme.prime.eval.api;
20+
```java
21+
package com.acme.prime.eval.api;
22+
/**
23+
* A service that evaluates an expression and returns the result
24+
*/
25+
public interface Eval {
2126
/**
22-
* A service that evaluates an expression and returns the result
27+
* Evaluate an expression and return the result.
2328
*/
24-
public interface Eval {
25-
/**
26-
* Evaluate an expression and return the result.
27-
*/
28-
double eval(String expression) throws Exception;
29-
}
29+
double eval(String expression) throws Exception;
30+
}
31+
```
3032

3133
Ok, it does not get a lot easier than this!
3234

@@ -78,17 +80,21 @@ The box with rounded corners represents a bundle; the inside black box represent
7880

7981
You might not have noticed it but you actually semantically versioned this package as well (don't you love magic?). When you look in the `com.acme.prime.eval.api` package you will find the `package-info.java` file. Double clicking will show the contents. In this file we define the version of the package. If you make modifications to the package, you should always update the version in this file as well.
8082

81-
@org.osgi.annotation.versioning.Version("1.0.0")
82-
package com.acme.prime.eval.api;
83-
83+
```java
84+
@org.osgi.annotation.versioning.Version("1.0.0")
85+
package com.acme.prime.eval.api;
86+
```
87+
8488
### Provider & Consumer Types
8589

8690
In this API, any party that will implement the `Eval` interface is considered to be the _provider_. A provider must fully implement a contract that has virtually no backward compatibility unlike _consumers_ of this API. Any change in the version that affects the public API must result in rebuild of the provider's bundle. That is, if our version here goes to 1.1 we want to make sure our providers that implemented 1.0 are no longer compatible.
8791

8892
Obviously it is a nightmare to ensure that the proper version ranges are used. We can significantly help the provider by adding an annotation to this interface:
8993

90-
@ProviderType
91-
public interface Eval { ... }
94+
```java
95+
@ProviderType
96+
public interface Eval { ... }
97+
```
9298

9399
The bnd tool will now automatically ensure that any _implementers_ of this interface use semantic versioning to import the package with a minor range, for example `[1.0,1.1)`.
94100

0 commit comments

Comments
 (0)