Skip to content

Commit 217bf4e

Browse files
Merge commit 'fde53e04d783df8d25c37e421ed5b83907a30db8' into HEAD
2 parents 8496cf8 + fde53e0 commit 217bf4e

18 files changed

+879
-12
lines changed

.gitignore

+5-12
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,11 @@ c/common/tools/macro_utils_h_generator/macro_utils_h_generator.exe
181181
**/hg/
182182

183183
# Java
184-
java/**/.idea/
185-
java/**/out/
186-
java/**/target/
187-
java/**/*.iml
188-
java/**/*dependency-reduced-pom.xml
184+
**/java/**/.idea/
185+
**/java/**/out/
186+
**/java/**/target/
187+
**/java/**/*.iml
188+
**/java/**/*dependency-reduced-pom.xml
189189
tools/jenkins-cli.jar
190190

191191
# Node.js
@@ -197,13 +197,6 @@ tools/jenkins-cli.jar
197197
typings/**
198198
.vscode/**
199199

200-
csharp/NuGet/*.exe
201-
csharp/NuGet/*.nupkg
202-
csharp/.vs/*
203-
service/java/.idea
204-
service/java/target
205-
service/java/iot.service.sdk.java.iml
206-
207200
# ignore cmake build folder
208201
.cmake/**
209202
build/**

CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ function(add_module_to_solution undecoratedModuleName)
4040
PROPERTIES FOLDER "Modules/${undecoratedModuleName}")
4141
endfunction()
4242

43+
function(add_binding_to_solution bindingLanguage)
44+
set_target_properties(${bindingLanguage} PROPERTIES FOLDER "Bindings")
45+
endfunction()
46+
4347
function(add_sample_to_solution sampleName)
4448
set_target_properties(${sampleName} PROPERTIES FOLDER "AzureIoTGateway_Samples")
4549
endfunction()

bindings/java/devdoc/Design.png

13.3 KB
Loading

bindings/java/devdoc/Design2.png

20.7 KB
Loading
+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
Java Binding High Level Design
2+
==============================
3+
4+
Overview
5+
--------
6+
7+
This document describes the high level design of the Java binding mechanism used
8+
by the Azure IoT Gateway SDK. It details how Java modules running inside of the
9+
JVM will interact with the native gateway core.
10+
11+
Design
12+
------
13+
14+
![](Design.png)
15+
16+
Java Module Host
17+
----------------
18+
19+
The **Java Module Host** is a C module that
20+
21+
1. Creates the JVM (Java Virtual Machine) the first time a Java module is
22+
attempting to connect to the gateway.
23+
24+
2. Brokers calls **to** the Java module (create, destroy, receive).
25+
26+
Because [JNI](http://docs.oracle.com/javase/8/docs/technotes/guides/jni/) (Java
27+
Native Interface) only allows one JVM instance per process, the **Java Module
28+
Host** will create a JVM **only once** when the first Java module is loading.
29+
Subsequent attempts to load additional Java modules will load and run those
30+
modules in the same JVM that was originally created. The JSON configuration for
31+
this module will be similar to the configuration for the Node Module Host:
32+
33+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ json
34+
{
35+
"modules": [
36+
{
37+
"module name": "java_poller",
38+
"module path": "/path/to/java_module_host.so|.dll",
39+
"args": {
40+
"class_path": "/path/to/relevant/class/files",
41+
"class_name": "Poller",
42+
"args": {
43+
"frequency": 30
44+
},
45+
"jvm_options": {
46+
"version": 8,
47+
"debug": true,
48+
"debug_port": 9876,
49+
"verbose": false,
50+
"additional_options": [
51+
"-Djava.version=1.8"
52+
]
53+
}
54+
}
55+
}
56+
]
57+
}
58+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59+
60+
or:
61+
62+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ json
63+
{
64+
"modules": [
65+
{
66+
"module name": "java_poller",
67+
"module path": "/path/to/java_module_host.so|.dll",
68+
"tags": ["java"],
69+
"args": {
70+
"class_path": "/path/to/relevant/class/files",
71+
"class_name": "Poller",
72+
"args": {
73+
"frequency": 30
74+
}
75+
}
76+
}
77+
]
78+
}
79+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
80+
81+
*You might have noticed a tags section. When processing the input JSON
82+
configuration file, the Gateway SDK will insert everything within the JSON
83+
object for the specified tag within the tags array into the args section for the
84+
corresponding module (please see \_\_\_\_ for more detailed guidance on
85+
constructing a JSON configuration).*
86+
87+
 
88+
89+
As usual, the `module path` specifies the path to the DLL/SO that implements the
90+
**Java Module Host**. The `args.class_path` specifies the path to the directory
91+
where all necessary Java class files are located, `args.class_name` is the name
92+
of the class that implements the module code, and finally `args.jvm_options` is
93+
a JSON object containing any options to be passed to the JVM upon creation.
94+
95+
 
96+
97+
Gateway Module (Java)
98+
---------------------
99+
100+
The **Java Module Host** will handle calling into the gateway module written in
101+
Java when necessary, therefore each module written in Java must implement the
102+
same `IGatewayModule` interface shown below:
103+
104+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ java
105+
public interface IGatewayModule {
106+
107+
/**
108+
* The create method is called by the subclass constructor when the native
109+
* Gateway creates the Module. The constructor
110+
* should save both the {@code moduleAddr} and {@code bus} parameters.
111+
*
112+
* @param moduleAddr The address of the native module pointer
113+
* @param bus The {@link MessageBus} to which this Module belongs
114+
* @param configuration The configuration for this module represented as a JSON
115+
* string
116+
*/
117+
void create(long moduleAddr, MessageBus bus, String configuration);
118+
119+
/**
120+
* The destroy method is called on a {@link GatewayModule} before it is about
121+
* to be "destroyed" and removed from the gateway.
122+
* Once a module is removed from the gateway, it may no longer send or receive
123+
* messages.
124+
*
125+
* The destroy() and receive() methods are guaranteed to not be called
126+
* simultaneously.
127+
*/
128+
void destroy();
129+
130+
/**
131+
* The receive method is called on a {@link GatewayModule} whenever it receives
132+
* a message.
133+
*
134+
* The destroy() and receive() methods are guaranteed to not be called
135+
* simultaneously.
136+
*
137+
* @param buffer The message content
138+
*/
139+
void receive(byte[] buffer);
140+
}
141+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142+
143+
To simplify this, the Azure IoT Gateway SDK provides an abstract `GatewayModule`
144+
class which implements the `IGatewayModule` interface. Module-implementers
145+
should extend this abstract class when creating a module.
146+
147+
 
148+
149+
Exactly like a standard gateway module written in C, the gateway will handle
150+
making calls to `Module_Create`, `Module_Receive`, and `Module_Destroy`. These
151+
three functions are implemented by the **Java Module Host** which handles the
152+
communication to the gateway module written in Java. Below is a description of
153+
what the **Java Module Host** will do in each of these cases:
154+
155+
### Module\_Create
156+
157+
When the **Java Module Host**’s `Module_Create` function is invoked by the
158+
gateway, it:
159+
160+
- Creates a JVM with the provided JVM configuration if this is the first Java
161+
module added to the gateway.
162+
163+
- Constructs a `MessageBus` Java object using the `MESSAGE_BUS_HANDLE`.
164+
165+
- Finds the module’s class with the name specified by the `args.class_name`,
166+
invokes the constructor passing in the `MODULE_HANDLE`, `MessageBus` object,
167+
the JSON args string for that module, and creates the Java module.
168+
169+
- Gets a global reference to the newly created `GatewayModule` object to be saved by
170+
the `JAVA_MODULE_HOST_HANDLE`.
171+
172+
### Module\_Receive
173+
174+
When the **Java Module Host**’s `Module_Receive` function is invoked by the
175+
gateway, it:
176+
177+
- Serializes the `MESSAGE_HANDLE` content and properties and invokes the
178+
`receive` method implemented by the Java module with the `MODULE_HANDLE` and
179+
the serialized message.
180+
181+
### Module\_Destroy
182+
183+
When the **Java Module Host**’s `Module_Destroy` function is invoked by the
184+
gateway, it:
185+
186+
- Attaches the current thread to the JVM
187+
188+
- Invokes the `destroy` method implemented by the Java module.
189+
190+
- Deletes the global reference to the Java module object.
191+
192+
- Destroys the JVM if it is the last Java module to be destroyed.
193+
194+
Communication **FROM** the Java module
195+
--------------------------------------
196+
197+
As previously mentioned, the **Java Module Host** will only handle communication
198+
from the native gateway process **to** the Java module. In order to communicate
199+
**from** the Java module to the native gateway process, the `MessageBus` class
200+
must be used. The `MessageBus` class provides a method to publish messages onto
201+
the native Message Bus and loads a dynamic library that implements expected
202+
functions for publishing onto the native Message Bus. So, the above diagram
203+
should look a bit more like this:
204+
205+
![](Design2.png)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Module Requirements
2+
3+
## Overview
4+
5+
The GatewayModule abstract class must be extended by any module written in Java; all
6+
Java modules must extend from the same abstract class. All methods to be
7+
implemented by the module-creator will be called by the gateway when necessary.
8+
9+
## References
10+
11+
[module.h](../../../../../../../../../core/devdoc/module.md)
12+
13+
## Exposed API
14+
```java
15+
public abstract class GatewayModule {
16+
protected GatewayModule(long address, MessageBus bus, String configuration);
17+
abstract void receive(Message message);
18+
abstract void destroy();
19+
}
20+
```
21+
22+
## Module
23+
```java
24+
public GatewayModule(long address, MessageBus bus, String configuration);
25+
```
26+
**SRS_JAVA_GATEWAY_MODULE_14_001: [** The constructor shall save `address`, `bus`,
27+
and `configuration` into class variables. **]**
28+
29+
**SRS_JAVA_GATEWAY_MODULE_14_002: [** If `address` or `bus` is `null` the constructor
30+
shall throw an IllegalArgumentException. **]**
31+
32+
When extending this abstract class, the module-creator must create their own
33+
constructor which calls this super constructor as the first statement.
34+
35+
## receive
36+
```java
37+
public void receive(Message message);
38+
```
39+
This method must be implemented by the module-creator. The method takes the
40+
native address of the `MODULE_HANDLE` and a byte array representing the serialized
41+
`Message`. This method will be called when a message is received for this Module.
42+
43+
## destroy
44+
```java
45+
public void destroy();
46+
```
47+
This method must be implemented by the module-creator. The method takes the
48+
native address of the `MODULE_HANDLE`. This method will be called when the module
49+
is about to be destroyed. Once destroyed, a module can no longer send or receive
50+
messages.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# MessageBus Requirements
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Message Requirements
2+
3+
## Overview
4+
5+
A message to be used by the Java module implementer. A message will always be serialized before publishing to the native gateway message bus.
6+
7+
## References
8+
9+
[message.h](../../../../../../../../../core/devdoc/message_requirements.md)
10+
11+
## Exposed API
12+
```java
13+
public final class Message implements Serializable{
14+
15+
private Map<String, String> properties;
16+
17+
private String content;
18+
19+
public Message(String content, Map<String, String> properties);
20+
public Message(String content);
21+
public Message(byte[] serializedMessage);
22+
public Map<String, String> getProperties();
23+
public String getContent();
24+
public byte[] toByteArray();
25+
}
26+
```
27+
28+
## Message
29+
```java
30+
public Message(byte[] serializedMessage | String content[, Map<String, String> properties]);
31+
```
32+
**SRS_JAVA_MESSAGE_14_001: [** The constructor shall create a Message object by deserializing the byte array. **]**
33+
34+
**SRS_JAVA_MESSAGE_14_002: [** If the byte array is malformed, the function shall throw an IllegalArgumentException. **]**
35+
36+
**SRS_JAVA_MESSAGE_14_003: [** The constructor shall save the message content and properties map. **]**
37+
38+
## toByteArray
39+
```java
40+
public byte[] toByteArray();
41+
```
42+
**SRS_JAVA_MESSAGE_14_004: [** The function shall serialize the Message content and properties according to the specification in [message.h](../../../../../../../../../core/devdoc/message_requirements.md) **]**
43+
44+
**SRS_JAVA_MESSAGE_14_005: [** The function shall return `null` if the Message could not be serialized. **]**

0 commit comments

Comments
 (0)