This repository has been archived by the owner on Oct 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
307 lines (227 loc) · 21.3 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>swookiee REST Services Runtime by swookiee</title>
<link rel="stylesheet" href="stylesheets/styles.css">
<link rel="stylesheet" href="stylesheets/pygment_trac.css">
<script src="javascripts/scale.fix.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div class="wrapper">
<header>
<h1 class="header">swookiee REST Services Runtime</h1>
<p class="header"></p>
<ul>
<li><a class="buttons github" href="https://github.com/swookiee">GitHub Profile</a></li>
</ul>
</header>
<section>
<p><a href="https://travis-ci.org/swookiee/com.swookiee.runtime"><img src="https://travis-ci.org/swookiee/com.swookiee.runtime.svg?branch=develop" alt="Build Status"></a></p>
<h2>
<a name="what-is-swookiee" class="anchor" href="#what-is-swookiee"><span class="octicon octicon-link"></span></a>What is swookiee*</h2>
<p>This is how a shaved wookiee could look like:</p>
<p><img src="https://raw.github.com/swookiee/swookiee.github.io/master/images/swookiee.png" alt="shaved wookiee"></p>
<p>Swookiee basically is a JVM Runtime for REST Services. It is lightweight (~17 MB, yeah... "lightweight") and includes libraries like guava, joda-time, metrics, etc. It also supports service implementation written in Groovy and Scala (+7MB each). It uses a JAX-RS 2 (Jersey), Jetty, Jackson stack on top of the Equinox OSGi runtime to serve REST Services. swookiee also provides multiple REST APIs to deploy and control services and components via REST.</p>
<p>Our main goals are:</p>
<ul>
<li>simplify exposing REST Services in the JVM</li>
<li>JVM-Polyglot: Solve problems in best fit language</li>
<li>reduce mandatory infrastructure and architectural knowledge from developers</li>
<li>define boundaries and APIs</li>
<li>enable deployment on artifact level (very simple OSGi <a href="https://github.com/osgi/design/tree/master/rfcs/rfc0182">RFC-182 implementation</a>)</li>
<li>increase transparency through direct metrics, graphite and JSON logging support</li>
</ul><h2>
<a name="build--start" class="anchor" href="#build--start"><span class="octicon octicon-link"></span></a>Build & start</h2>
<p>Build & Start</p>
<pre lang="shell"><code>cd com.swookiee.runtime
mvn clean install
cd com.swookiee.runtime
mvn exec:exec
</code></pre>
<h2>
<a name="web-console" class="anchor" href="#web-console"><span class="octicon octicon-link"></span></a>Web Console</h2>
<p>When swookiee is up and running the Web Console can be accessed via <a href="http://localhost:8080/system/console"><code>http://localhost:8080/system/console</code></a>. The default credentials are <code>admin:admin123</code>.</p>
<h2>
<a name="rest-services" class="anchor" href="#rest-services"><span class="octicon octicon-link"></span></a>REST Services</h2>
<p>To expose a REST service in swookiee you can describe the REST API with a simple interface:</p>
<div class="highlight highlight-java"><pre><span class="nd">@Path</span><span class="o">(</span><span class="s">"/hello"</span><span class="o">)</span>
<span class="nd">@Produces</span><span class="o">(</span><span class="n">APPLICATION_JSON</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">HelloWorld</span> <span class="o">{</span>
<span class="nd">@GET</span>
<span class="n">String</span> <span class="nf">hello</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<p>Through using the given <a href="http://www.osgi.org/javadoc/r5/cmpn/org/osgi/service/component/annotations/Component.html"><code>@Component</code></a> annotation the implementation of the interface will be exposed.</p>
<div class="highlight highlight-java"><pre><span class="nd">@Component</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorldService</span> <span class="kd">implements</span> <span class="n">HelloWorld</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">hello</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">"Hola!"</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>A REST service will be exposed using the <a href="https://github.com/hstaudacher/osgi-jax-rs-connector">OSGi - JAX-RS Connector</a>. Thus, every JAX-RS component which is an available OSGi service will also be published via Jersey. You will find a deteiles Jersey user guide <a href="https://jersey.java.net/documentation/latest">here</a>.</p>
<h2>
<a name="filters-exception-mapping-" class="anchor" href="#filters-exception-mapping-"><span class="octicon octicon-link"></span></a>Filters, Exception Mapping, ...</h2>
<p>In addition to provide services you might need to register Filter (e.g. for CORS). This can be done via <code>ContainerResponseFilter</code> and <code>ContainerRequestFilter</code> implementations:</p>
<div class="highlight highlight-java"><pre><span class="nd">@Component</span>
<span class="nd">@Provider</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyFilter</span> <span class="kd">implements</span> <span class="n">ContainerResponseFilter</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">filter</span><span class="o">(</span><span class="kd">final</span> <span class="n">ContainerRequestContext</span> <span class="n">requestContext</span><span class="o">,</span> <span class="kd">final</span> <span class="n">ContainerResponseContext</span> <span class="n">responseContext</span><span class="o">)</span> <span class="o">{</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<div class="highlight highlight-java"><pre><span class="nd">@Component</span>
<span class="nd">@Provider</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyFilter</span> <span class="kd">implements</span> <span class="n">ContainerRequestFilter</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">filter</span><span class="o">(</span><span class="kd">final</span> <span class="n">ContainerRequestContext</span> <span class="n">requestContext</span><span class="o">)</span> <span class="o">{</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>In order to register an exception mapper you have to implement the <code>ExceptionMapper</code> interface:</p>
<div class="highlight highlight-java"><pre><span class="nd">@Component</span>
<span class="nd">@Provider</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyExceptionMapper</span> <span class="kd">implements</span> <span class="n">ExceptionMapper</span><span class="o"><</span><span class="n">MyException</span><span class="o">></span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">Response</span> <span class="nf">toResponse</span><span class="o">(</span><span class="kd">final</span> <span class="n">MyException</span> <span class="n">exception</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">Response</span><span class="o">.</span><span class="na">status</span><span class="o">(</span><span class="n">Status</span><span class="o">.</span><span class="na">INTERNAL_SERVER_ERROR</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h2>
<a name="json-logging-output" class="anchor" href="#json-logging-output"><span class="octicon octicon-link"></span></a>JSON logging output</h2>
<p>In case you want to use logstash and kibana to analyze your logs you might want to use JSON as an output format.
This can be achieved through setting the property <code>productionLogging</code> to <code>true</code>. To change the output folder configure <code>loggingDirectory</code> with your desired path. The output filename will be <code>osgi-json.log</code>. </p>
<h2>
<a name="deployment-and-runtime-management-via-rest" class="anchor" href="#deployment-and-runtime-management-via-rest"><span class="octicon octicon-link"></span></a>Deployment and runtime management via REST</h2>
<p><a href="https://github.com/osgi/design/tree/master/rfcs/rfc0182">RFC-182</a></p>
<h2>
<a name="configuration" class="anchor" href="#configuration"><span class="octicon octicon-link"></span></a>Configuration</h2>
<p>The Swookiee Runtime can be configured programmatically and via the UI of the Web Console. </p>
<h3>
<a name="programmatic-configuration" class="anchor" href="#programmatic-configuration"><span class="octicon octicon-link"></span></a>Programmatic Configuration</h3>
<p>The programmatic configuration can be done via an API on top of the OSGi Configuration Admin. The full sample can be found <a href="https://github.com/swookiee/swookiee-samples/tree/develop/config">here</a></p>
<p>Define a POJO with the components you want to configure. In this case we want to change the admin user credentials and the graphite reporter configuration:</p>
<div class="highlight highlight-java"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Configuration</span> <span class="o">{</span>
<span class="kd">public</span> <span class="n">AdminUserConfiguration</span> <span class="n">adminUserConfiguration</span><span class="o">;</span>
<span class="kd">public</span> <span class="n">GraphiteReporterConfiguration</span> <span class="n">graphiteReporterConfiguration</span><span class="o">;</span>
<span class="o">}</span>
</pre></div>
<p>Define a YAML file which matches the attributes of your POJO. Additionally set the desired parameter values:</p>
<div class="highlight highlight-yml"><pre><span class="l-Scalar-Plain">adminUserConfiguration</span><span class="p-Indicator">:</span>
<span class="l-Scalar-Plain">username</span><span class="p-Indicator">:</span> <span class="s">"admin"</span>
<span class="l-Scalar-Plain">password</span><span class="p-Indicator">:</span> <span class="s">"admin42"</span>
<span class="l-Scalar-Plain">graphiteReporterConfiguration</span><span class="p-Indicator">:</span>
<span class="l-Scalar-Plain">graphiteHost</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">localhost</span>
<span class="l-Scalar-Plain">graphitePort</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">2003</span>
<span class="l-Scalar-Plain">reportingIntervalInSeconds</span> <span class="p-Indicator">:</span> <span class="l-Scalar-Plain">42</span>
<span class="l-Scalar-Plain">reportingEnabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
<span class="l-Scalar-Plain">reportingPrefix</span><span class="p-Indicator">:</span> <span class="s">"configDemo"</span>
</pre></div>
<p>In order to set your configuration values to the addressed components you can create a Declarative Service Component which is then using <code>ConfigurationUtils</code> to set your configuration parameters</p>
<div class="highlight highlight-java"><pre><span class="nd">@Component</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ConfigurationProviderSample</span> <span class="o">{</span>
<span class="kd">private</span> <span class="n">ConfigurationAdmin</span> <span class="n">configAdmin</span><span class="o">;</span>
<span class="nd">@Activate</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">activate</span><span class="o">(</span><span class="kd">final</span> <span class="n">BundleContext</span> <span class="n">bundleContext</span><span class="o">)</span> <span class="o">{</span>
<span class="kd">final</span> <span class="n">URL</span> <span class="n">configurationFile</span> <span class="o">=</span> <span class="n">bundleContext</span><span class="o">.</span><span class="na">getBundle</span><span class="o">().</span><span class="na">getResource</span><span class="o">(</span><span class="s">"Configuration.yaml"</span><span class="o">);</span>
<span class="n">ConfigurationUtils</span><span class="o">.</span><span class="na">applyConfiguration</span><span class="o">(</span><span class="n">Configuration</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">configurationFile</span><span class="o">,</span> <span class="n">configAdmin</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Reference</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setConfigurationAdmin</span><span class="o">(</span><span class="kd">final</span> <span class="n">ConfigurationAdmin</span> <span class="n">configurationAdmin</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">configAdmin</span> <span class="o">=</span> <span class="n">configurationAdmin</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">unsetConfigurationAdmin</span><span class="o">(</span><span class="kd">final</span> <span class="n">ConfigurationAdmin</span> <span class="n">configurationAdmin</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">configAdmin</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<h3>
<a name="ui" class="anchor" href="#ui"><span class="octicon octicon-link"></span></a>UI</h3>
<p>Most configuration parameters can be controlled via the Web Console: <a href="http://localhost:8080/system/console/configMgr">http://localhost:8080/system/console/configMgr</a></p>
<h2>
<a name="pushing-metrics-to-graphite" class="anchor" href="#pushing-metrics-to-graphite"><span class="octicon octicon-link"></span></a>Pushing metrics to graphite</h2>
<p>Every published REST interface will be monitored via metrics. In addition basic JVM statistics will be collected. In order to configure the graphite reporter you can configure various settings:</p>
<div class="highlight highlight-yml"><pre><span class="l-Scalar-Plain">graphiteReporterConfiguration</span><span class="p-Indicator">:</span>
<span class="l-Scalar-Plain">graphiteHost</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">localhost</span>
<span class="l-Scalar-Plain">graphitePort</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">2003</span>
<span class="l-Scalar-Plain">reportingIntervalInSeconds</span> <span class="p-Indicator">:</span> <span class="l-Scalar-Plain">42</span>
<span class="l-Scalar-Plain">reportingEnabled</span><span class="p-Indicator">:</span> <span class="l-Scalar-Plain">true</span>
<span class="l-Scalar-Plain">reportingPrefix</span><span class="p-Indicator">:</span> <span class="s">"configDemo"</span>
</pre></div>
<p>Example Screenshot of some made up traffic:
<img src="https://raw.github.com/swookiee/swookiee.github.io/master/screenshots/graphite.png" alt="graphite"></p>
<h2>
<a name="swagger" class="anchor" href="#swagger"><span class="octicon octicon-link"></span></a>Swagger</h2>
<p>The above described REST Resource can be enriched using <code>swagger-annotations</code>. A full sample can be found <a href="https://github.com/swookiee/swookiee-samples/tree/develop/demo.swagger">here</a>.</p>
<p>We could add the <code>@Api</code> and <code>@ApiOperation</code> annotations to our sample service:</p>
<div class="highlight highlight-java"><pre><span class="nd">@Path</span><span class="o">(</span><span class="n">Status</span><span class="o">.</span><span class="na">PATH</span><span class="o">)</span>
<span class="nd">@Produces</span><span class="o">(</span><span class="n">APPLICATION_JSON</span><span class="o">)</span>
<span class="nd">@Api</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="na">PATH</span><span class="o">,</span> <span class="n">description</span> <span class="o">=</span> <span class="s">"Returns a status"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">Status</span> <span class="o">{</span>
<span class="kd">final</span> <span class="kd">static</span> <span class="n">String</span> <span class="n">PATH</span> <span class="o">=</span> <span class="s">"/status"</span><span class="o">;</span>
<span class="nd">@GET</span>
<span class="nd">@ApiOperation</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"Ping the Status API to receive a StatusObject"</span><span class="o">,</span> <span class="n">response</span> <span class="o">=</span> <span class="n">StatusObject</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">StatusObject</span> <span class="nf">ping</span><span class="o">();</span>
<span class="o">}</span>
</pre></div>
<p>The following steps are important to let swookiee deliver you swagger api documentation:</p>
<ol>
<li>Make sure you have the <code>maven-swagger-plugin</code> configured properly and you are able to see generated swagger json files? Also make sure that the <code><basePath>/services</basePath></code> is set according to your configuration. Otherwise you won’t be able to test you API.</li>
<li>Is the generated json part of your bundle/artefact/<code>.jar</code>? Is the folder accessable from within the Bundle? Set the the <code>Bundle-Classpath</code> to include the documentation folder.</li>
<li>Add the <code>X-Swagger-Documentation</code> header in you <code>MANIFEST.MF</code> or your <code>maven-bundle-plugin</code> configuration to point to the documentation folder inside the <code>jar</code>, such as: <code>X-Swagger-Documentation: /swagger</code>.</li>
</ol><p>After installing the bundle you will find the <code>swagger-ui</code> under <code>http://localhost:8080/swagger/index.html</code>. Click on the small swookiee icon to see your documentation and test your API.</p>
<p>Screenshot of the sample:
<img src="https://raw.github.com/swookiee/swookiee.github.io/master/screenshots/swagger.png" alt="swagger"></p>
<h2>
<a name="archetypes--tooling--samples" class="anchor" href="#archetypes--tooling--samples"><span class="octicon octicon-link"></span></a>Archetype(s) & Tooling & Samples</h2>
<h3>
<a name="samples--archetype" class="anchor" href="#samples--archetype"><span class="octicon octicon-link"></span></a>Samples & Archetype</h3>
<ul>
<li><a href="https://github.com/swookiee/swookiee-samples">Configuration & Swagger</a></li>
<li><a href="https://github.com/swookiee/com.swookiee.archetype">Archetype & Simple REST Service</a></li>
</ul><h3>
<a name="eclipse" class="anchor" href="#eclipse"><span class="octicon octicon-link"></span></a>Eclipse</h3>
<h3>
<a name="netbeans" class="anchor" href="#netbeans"><span class="octicon octicon-link"></span></a>Netbeans</h3>
<h2>
<a name="todos" class="anchor" href="#todos"><span class="octicon octicon-link"></span></a>Todos</h2>
<ul>
<li>[ ] provide rpm, deb and other packages</li>
<li>[ ] more JVM languages? (see <a href="https://github.com/swookiee/com.swookiee.runtime/tree/feature/clojure_support">clojure branch</a>)</li>
<li>[ ] Running swookiee programatically</li>
<li>[ ] Integration Test Tooling</li>
</ul><h2>
<a name="thanks" class="anchor" href="#thanks"><span class="octicon octicon-link"></span></a>Thanks</h2>
<p>Many thanks to <strong>Intuit Data Engineering & Analytics</strong> for the support!</p>
<p><a href="http://intuit.com"><img src="https://raw.githubusercontent.com/swookiee/swookiee.github.io/master/images/idea_logo.jpg" alt="IDEA"></a></p>
<h2>
<a name="license" class="anchor" href="#license"><span class="octicon octicon-link"></span></a>License</h2>
<p>The code is published under the terms of the <a href="http://www.eclipse.org/legal/epl-v10.html">Eclipse Public License, version 1.0</a>.</p>
<p>* derived from "shaved wookiee"</p>
</section>
<footer>
<p><small>Hosted on <a href="http://pages.github.com">GitHub Pages</a> using the Dinky theme</small></p>
</footer>
</div>
<!--[if !IE]><script>fixScale(document);</script><![endif]-->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-48180947-1");
pageTracker._trackPageview();
} catch(err) {}
</script>
</body>
</html>