| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version |
| 2.0 (the "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 Unless required by |
| applicable law or agreed to in writing, software distributed under the |
| License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
| CONDITIONS OF ANY KIND, either express or implied. See the License for |
| the specific language governing permissions and limitations under the |
| License. |
| --> |
| <html> |
| <link rel=StyleSheet href="style/site.css" type="text/css"> |
| <header> |
| <TABLE width="100%" cellpadding="0" cellspacing="0"> |
| <TR width="100%"> |
| <TD id="cell-0-0" colspan="2"> </TD> |
| <TD id="cell-0-1"> </TD> |
| <TD id="cell-0-2" colspan="2"> </TD> |
| </TR> |
| <TR width="100%"> |
| <TD id="cell-1-2" colspan="5"> |
| <DIV style="padding: 40px;"> |
| <DIV id="banner"><!-- Banner --> |
| <TABLE border="0" cellpadding="0" cellspacing="0" width="100%"> |
| <TR> |
| <TD align="left" class="topbardiv" nowrap=""><A |
| href="http://aries.apache.org/" |
| title="Apache Aries "> <IMG border="0" |
| src="images/Arieslogo_Horizontal.gif"> </A></TD> |
| <TD align="right" nowrap=""> |
| <div class=tutorialHeader>Blueprint Tutorial</div> |
| </TR> |
| </TABLE> |
| </DIV> |
| </DIV> |
| </TD> |
| |
| </TR> |
| <TR width="100%"> |
| <TD id="cell-2-0" colspan="2"> </TD> |
| <TD id="cell-2-1"> </TD> |
| <TD id="cell-2-2" colspan="2"> </TD> |
| </TR> |
| </TABLE> |
| </header> |
| <body> |
| <div class=wiki-content> |
| <h1>Setting up</h1> |
| |
| <p>This set of instructions will take you through modifying and |
| running the code in the tutorial. To run through the tutorial you will |
| need: |
| |
| <ul> |
| <li>A laptop</li> |
| <li>Java (Version 1.6 or greater)</li> |
| <li>Maven (Version 2.2.1 or greater)</li> |
| <li>A working network connection</li> |
| </ul> |
| |
| |
| <p>Before beginning the tutorial code we need to check that you can |
| run the OSGi platform and applications. We will refer to the directory |
| that you extracted the zip or tar file in as [toplevel]. We will use |
| Linux commands in the instructions - if you don't know what the |
| equivalent Windows commands are please ask.</p> |
| |
| <p>To check that you are able to run the OSGi sample code run these |
| commands from a shell prompt:</p> |
| <div class=code>cd [toplevel]/scripts<br> |
| ./start_platform.sh</div> |
| <p>You should see the Equinox OSGi console come up. The 'ss' command |
| lists the state of the platform. Issue the 'ss' command: |
| <div class=code>osgi> ss</div> |
| You should see 8 bundles (numbered 0-7). |
| |
| <p>Leave this running in one window as we will return to it later. Open a new window/shell, we |
| will use the new shell to run some samples.</p> |
| |
| <p>In the new shell, change directory to [toplevel]/bin and copy the following |
| three files into the [toplevel]/dropins directory:</p> |
| <div class=code>org.apache.aries.tutorials.blueprint.greeter.api-0.1-SNAPSHOT.jar<br> |
| org.apache.aries.tutorials.blueprint.greeter.server.osgi-0.1-SNAPSHOT.jar<br> |
| org.apache.aries.tutorials.blueprint.greeter.client.osgi-0.1-SNAPSHOT.jar<br> |
| </div> |
| <p>This installs those bundles in the OSGi framework. Back in the OSGi console window, type 'ss' again, you should see |
| three new bundles in the 'INSTALLED' state. Start all three new bundles |
| starting with the <b>greeter.server.osgi</b> bundle. To do this, issue the 'start' command |
| followed by the bundle ID:</p> |
| <div class=code>osgi> start [ID]</div> |
| <p>Where 'ID' is the number of the bundle.</p> |
| |
| <p>When you start the <b>greeter.client.osgi</b> bundle you will see some output - we |
| will come back to this later in the tutorial.</p> |
| |
| <p>Back in the other shell, navigate to [toplevel]/dropins and |
| delete everything - this will uninstall the bundles.</p> |
| |
| <p>Finally check the OSGi console to confirm that the three |
| bundles have gone by issuing another 'ss' command.</p> |
| |
| <p>Later in the tutorial you will be using Maven to build the sample |
| code. |
| |
| <h1>Converting the OSGi Client.</h1> |
| |
| <p>The projects org.apache.aries.tutorials.blueprint.greeter.client.osgi, |
| org.apache.aries.tutorials.blueprint.greeter.server.osgi and |
| org.apache.aries.tutorials.blueprint.greeter.api |
| together comprise a simple application demonstrating |
| publication and consumption of an OSGi service. By following the steps |
| below, you will gradually migrate the application to use blueprint, |
| which will demonstrate how blueprint can help to simplify such projects.</p> |
| |
| <p>In the next section ('Minimum conversion') we will go through the |
| minimum number of steps necessary to convert the client code to use |
| blueprint. In the section after that ('Finishing the client') we will go |
| through some more extensive changes to the client which extend its use |
| of blueprint.</p> |
| |
| <h2>Minimum conversion</h2> |
| |
| |
| <p>In this section we will take the minimum number of actions to |
| convert the greeter client application to use blueprint.</p> |
| |
| <p>First, take a look at the the client class, the source is located here:</p> |
| <div class=code> |
| [toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.client.osgi/src/main/java/org/apache/aries/tutorials/blueprint/greeter/client/osgi/ClientBundleActivator.java |
| </div> |
| <p>This class (activator) does two things:</p> |
| <ol> |
| <li>Instantiates the test class (GreeterTestClient)</li> |
| <li>Invokes the 'doRequests()' method from the GreeterTestClient |
| class.</li> |
| </ol> |
| |
| <h3>Removing the activator</h3> |
| |
| |
| <p>In the following steps we will develop blueprint to carry out the tasks that are currently handled by the activator, the first |
| step is to delete the activator class. For example, on linux:</p> |
| <div class=code>rm |
| [toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.client.osgi/src/main/java/org/apache/aries/tutorials/blueprint/greeter/client/osgi/ClientBundleActivator.java |
| </div> |
| <p>The next step is to edit the file |
| [toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.client.osgi/pom.xml, and remove the line:</p> |
| <div class=code><Bundle-Activator>org.apache.aries.tutorials.blueprint.greeter.client.osgi.ClientBundleActivator</Bundle-Activator> |
| </div> |
| |
| <h3>Replacing the functionality of the activator with blueprint</h3> |
| |
| |
| <p>If you were to rebuild the bundle at this point it would still |
| build and deploy, but without the activator the test class would not be |
| invoked and there would be no output when the client bundle was started. |
| In this step we will use blueprint to replace what the activator was |
| doing - creating an instance of the test class and calling one of its |
| methods.</p> |
| |
| |
| <p>Start by adding an OSGI-INF/blueprint directory under the |
| org.apache.aries.tutorials.blueprint.greeter.client.osgi/src/main/resources folder:</p> |
| <div class=code>mkdir -p |
| [toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.client.osgi/src/main/resources/OSGI-INF/blueprint |
| </div> |
| <p>In the newly created blueprint directory, create a blueprint.xml |
| file containing the following blueprint 'template'.</p> |
| <div class=code><?xml version="1.0" encoding="UTF-8"?><br> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><br> |
| </blueprint><br> |
| </div> |
| |
| <p>Note: The name of the file can be anything you like that ends in |
| .xml - blueprint.xml is a popular choice.</p> |
| |
| <p>Now, add a bean element to represent the test class; remember the |
| activator was used to create an instance of this class, now we will use blueprint to do |
| the same. Add the bean element shown below within the blueprint XML element.</p> |
| <div class=code><bean id="clientBean" <br> |
| class="org.apache.aries.tutorials.blueprint.greeter.client.osgi.GreeterTestClient"> |
| </bean></div> |
| <p>The blueprint container will attempt to instantiate the class |
| (GreeterTestClient) with a zero argument constructor by default. However |
| - there is no zero argument constructor in the GreeterTestClient class; |
| the only constructor has the signature GreeterTestClient(BundleContext |
| b, String clientID). We can tell blueprint to use this by adding some |
| arguments inside the bean like this:</p> |
| <div class=code><argument ref="blueprintBundleContext"/><br> |
| <argument value="My blueprint client ID"/><br> |
| </div> |
| <p>These arguments will be fed to the constructor. The string "My |
| blueprint client ID" will be used directly, while the |
| 'blueprintBundleContext' references a special bean - we are not going to |
| worry about this now, it's beyond the scope of the tutorial.</p> |
| |
| <p>If we were to build and deploy now, we'd discover the |
| GreeterTestClient is constructed, but the 'doRequests' method is not invoked.</p> |
| |
| <p>For this last part of the puzzle, we'll use the blueprint bean |
| 'init-method' attribute, which specifies a method to be called after a |
| bean is constructed. To use the 'init-method', add</p> |
| <div class=code>init-method="doRequests"</div> |
| <p>to the bean element. You should now have something like this in |
| your blueprint xml file:</p> |
| <div class=code><?xml version="1.0" encoding="UTF-8"?><br> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><br> |
| <bean id="clientBean" class="org.apache.aries.tutorials.blueprint.greeter.client.osgi.GreeterTestClient"<br> |
| init-method="doRequests"><br> |
| <argument value="My blueprint client ID"/><br> |
| <argument ref="blueprintBundleContext"/><br> |
| </bean><br> |
| </blueprint><br> |
| </div> |
| <p>Finally we need to build and re-deploy the client we have just |
| changed.</p> |
| |
| <p>To build the code, run the script build.sh (or build.bat) in the |
| [toplevel]/scripts directory. |
| The commands are:</p> |
| <div class=code>./build.sh org.apache.aries.tutorials.blueprint.greeter.api<br> |
| ./build.sh org.apache.aries.tutorials.blueprint.greeter.client.osgi<br> |
| ./build.sh org.apache.aries.tutorials.blueprint.greeter.server.osgi<br> |
| </div> |
| |
| <p>To run your sample, from the the [toplevel]/scripts directory:</p> |
| <div class=code>./run.sh</div> |
| <p>this will copy the jar files generated in the build step to |
| [toplevel]/dropins and hence install the application.</p> |
| |
| <p>Now look back to the OSGi console, start the bundles (server |
| first!), and check that they run. Clean the dropins directory again by |
| removing all the files from it.</p> |
| |
| |
| <p>At this point we have a blueprint client running without a bundle |
| activator. However, when we look at the content of the |
| GreeterTestClient class, it's doing all sorts of OSGi service related things |
| that blueprint could do much more simply. In the next section we will see how |
| use of blueprint can lead to much a much cleaner service invocation.</p> |
| |
| <h2>Finishing the client</h2> |
| |
| |
| <p>The client code (GreeterTestClient) was written to demonstrate a |
| few common approaches to invoking an OSGi service. For example, there is |
| a proxy class, hiding a tracker, which passes the requests on |
| to the service (see inner class GreeterMessageServiceProxy). The really quite nasty |
| 'look it up and use it all in one hit.. ' approach |
| is demonstrated in the method doRequestUsingImmediateLookup().</p> |
| |
| <p>Those experienced with OSGi will recognise the usual hidden |
| selection of service usage bugs, for example, failing to unget the |
| service in all cases, not handling situations when the service goes away |
| after being looked up, etc.</p> |
| |
| <p>Blueprint can help us avoid most of the common errors |
| demonstrated in this code. So, let's get started and convert this client |
| code to use blueprint.</p> |
| |
| <h3>Removing the old test implementations</h3> |
| |
| |
| <p>The current contents of the client is written to show various |
| OSGi ways of invoking a service. Since we're going to have blueprint |
| take care of this for us, we can remove the old OSGi service API usage.</p> |
| |
| <p>In the class:</p> |
| <div class=code> |
| [toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.client.osgi/src/main/java/org/apache/aries/tutorials/blueprint/greeter/client/osgi/GreeterTestClient.java |
| </div> |
| <p>Remove the following methods: |
| <ul> |
| <li>doRequestUsingImmediateLookup</li> |
| <li>doRequestUsingTracker</li> |
| <li>doRequestUsingCachedService</li> |
| </ul> |
| |
| <p>Also remove: |
| <ul> |
| <li>The inner class 'GreeterMessageServiceProxy'</li> |
| <li>The field 'owningContext'</li> |
| <li>The field 'cachedService'</li> |
| <li>The field 'tracker'</li> |
| <li>The entire content of the constructor method, except the first |
| line.</li> |
| </ul> |
| |
| <p>Now, you should have removed everything from the class |
| except: |
| <ul> |
| <li>The field 'clientID'</li> |
| <li>The field 'proxy'</li> |
| <li>The first line of the constructor</li> |
| <li>The 'doRequests' method.</li> |
| <li>The 'doRequestUsingProxy' method.</li> |
| <li>The 'printResult' method.</li> |
| </ul> |
| |
| |
| |
| <h3>Preparing for blueprint</h3> |
| |
| |
| <p>In this section we will add code that makes the client a lot more |
| like a java-bean by adding a setter for the proxy and removing the old |
| bundle context related elements from both the Java code and blueprint |
| xml.</p> |
| |
| <p>Continuing to edit the GreeterTestClient class, remove all but |
| the first two lines of the 'doRequests' method, it should now just |
| contain:</p> |
| <div class=code>System.out.println("Proxy based...");<br> |
| doRequestUsingProxy();</div> |
| |
| <p>Now add a setter for the proxy,</p> |
| <div class=code>public void setProxy(GreeterMessageService p){<br> |
| this.proxy = p;<br> |
| }</div> |
| <p>and, since we're not using it any more, remove the BundleContext |
| from the class constructor. Like this: |
| |
| <div class=code>public GreeterTestClient(String clientID) {<br> |
| this.clientID = clientID;<br> |
| }<br> |
| </div> |
| |
| <p>Finally, save and close the GreeterTestClient class. |
| |
| <p>The last step is to modify the blueprint xml to reflect these |
| changes. Edit the blueprint xml you created earlier:</p> |
| <div class=code> |
| [toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.client.osgi/src/main/resources/OSGI-INF/blueprint/blueprint.xml |
| </div> |
| <p>Remove the following line from the blueprint xml</p> |
| <div class=code><argument ref="blueprintBundleContext"/></div> |
| <p>This ensures that the blueprint matches the modified constructor in the |
| GreeterTestClient class.</p> |
| |
| |
| <h3>Adding blueprint to the client</h3> |
| |
| |
| <p>At this point we have code which will compile, but is not yet |
| complete. We have a client that will instantly null pointer if we |
| attempt to run it. Looking back at the GreeterTestClient class, when the |
| doRequests() method is invoked by the init-method declaration in the |
| blueprint xml, this in turn calls doRequestUsingProxy() which calls |
| getGreetingMessage() on the proxy variable. However, this variable is |
| initialised to null and never changed.</p> |
| |
| <p>We need to make sure we set the 'proxy' variable. We can do this |
| using blueprint!</p> |
| |
| <p>Back in the xml file:</p> |
| <div class=code> |
| [toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.client.osgi/src/main/resources/OSGI_INF/blueprint/blueprint.xml |
| </div> |
| |
| <p>Add a 'reference' element, that refers to the greeter service. To |
| do this add the folowing xml inside <blueprint> but not inside the |
| <bean> element.</p> |
| <div class=code><reference id="greeterService" interface="org.apache.aries.tutorials.blueprint.greeter.api.GreeterMessageService"<br> |
| timeout="10000" availability="mandatory"/></div> |
| <p>This sets up a blueprint component with the ID 'greeterService', |
| which will appear to its users as an instance of the interface |
| specified, with its implementation being backed by an OSGi service |
| claiming to meet that interface.</p> |
| |
| <p>Note: This is the most simple possible blueprint service - there |
| are many more powerful ways to use services within blueprint.</p> |
| |
| <p>Notice that we added the 'availability="mandatory"' attribute. |
| This will ensure that the client will not start if if there are no |
| services available implementing the interface. If you started the client |
| before the service in any of the previous steps you would have seen a |
| stack trace, making the service mandatory avoids this issue.</p> |
| |
| <p>The last step is to inject the 'greeterService' reference into |
| our test client using a property element. Add this line inside the bean |
| definition</p> |
| <div class=code><property name="proxy" |
| ref="greeterService"/></div> |
| <p>This will invoke the 'setProxy' method we added earlier and pass |
| in a blueprint service proxy, hooked up to any OSGi service |
| implementing the GreeterMessageService.</p> |
| |
| |
| <p>The complete blueprint.xml file should now look like this:</p> |
| <div class=code><?xml version="1.0" encoding="UTF-8"?><br> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><br> |
| |
| <reference id="greeterService" interface="org.apache.aries.tutorials.blueprint.greeter.api.GreeterMessageService"<br> |
| timeout="10000" availability="mandatory"/><br> |
| <bean id="clientBean" class="org.apache.aries.tutorials.blueprint.greeter.client.osgi.GreeterTestClient"<br> |
| init-method="doRequests"><br> |
| <argument value="My blueprint client ID"/><br> |
| <property name="proxy" |
| ref="greeterService"/><br> |
| </bean><br> |
| </blueprint></div> |
| <p>That is all we need to do to the client. At this stage, rebuild |
| the client as you did at the end of the minimum conversion and watch it |
| running in the OSGi console. The steps are repeated here for |
| convenience.</p> |
| |
| <p>To build the code, run the script build.sh (or build.bat) in the |
| [toplevel]/scripts directory. If you are using your own Maven repository |
| the commands are:</p> |
| <div class=code> |
| ./build.sh org.apache.aries.tutorials.blueprint.greeter.client.osgi<br> |
| </div> |
| |
| <p>To run your sample, from the the [toplevel]/scripts directory:</p> |
| <div class=code>./run.sh</div> |
| <p>this will copy the jar files generated in the build step to |
| [toplevel]/dropins and hence install the application.</p> |
| |
| |
| <p>Now look back to the OSGi console, start the bundles (server |
| first!), and check that they run. Clean the dropins directory again by |
| removing all the files from it.</p> |
| |
| |
| |
| <p>We're done with the client, and it's time to turn our attention |
| to the server side of things. Converting the server is very similar to |
| converting the client, but a lot simpler, as the only OSGi related bits |
| in the current server are limited to instantiating and registering the |
| service.</p> |
| |
| <h1>Converting the OSGi service</h1> |
| |
| <p>The service creation and registration is once again being handled |
| by a Bundle Activator, this time it's at.. |
| <div class=code> |
| [toplevel]/org.apache.aries.tutorials.blueprint.greeter.server.osgi/src/main/java/org/apache/tutorials/blueprint/greeter/server/osgi/ServiceRegisteringActivator.java |
| </div> |
| <p>Have a quick look at what this class is doing, make a quick note |
| of how it creates and initialises the service implementation, and how it |
| manages the service registration.</p> |
| |
| <p>Delete the class. We'll be replacing it entirely with a blueprint |
| version.</p> |
| <p>Start by adding an OSGI-INF/blueprint directory to the |
| source/org.apache.aries.tutorials.blueprint.greeter.server.osgi/src/main/resources folder.</p> |
| |
| <p>In the blueprint directory, create an xml file called |
| blueprint.xml.</p> |
| |
| <p>In the xml file, add the main blueprint element and usual xml |
| boilerplate.</p> |
| <div class=code><?xml version="1.0" encoding="UTF-8"?><br> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><br> |
| </blueprint><br> |
| </div> |
| <p>Let's start by having blueprint create the instance of the |
| implementation of our service. Add a bean element with the service |
| implementation class "GreeterMessageServiceImpl" as its target class.</p> |
| <div class=code><bean id="serverBean" |
| class="org.apache.aries.tutorials.blueprint.greeter.server.osgi.GreeterMessageServiceImpl"> |
| </bean></div> |
| <p>Now we need to initalise it, just as the original activator did. |
| The activator set the sender id in the Service by using the 'setSender' |
| method. We can have blueprint do this for us with a property element.</p> |
| <div class=code><property name="sender" value="Blueprint Greeting Service"/></div> |
| <p>Great... we have a server bundle, which if built and |
| deployed, would create an implementation of the service and set the |
| sender id on it. Unfortunately, no-one would be able to see it as we have not published it |
| to the OSGi registry. The blueprint '<service>' element is required to publish the service:</p> |
| <div class=code><service id="greeterService"<br> |
| interface="org.apache.aries.tutorials.blueprint.greeter.api.GreeterMessageService"<br> |
| ref="serverBean"><br> |
| </service></div> |
| <p>Putting it all together, you should have ended up with something |
| a little like this...</p> |
| <div class=code><?xml version="1.0" encoding="UTF-8"?><br> |
| <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"><br> |
| |
| <bean id="serverBean" |
| class="org.apache.aries.tutorials.blueprint.greeter.server.osgi.GreeterMessageServiceImpl"><br> |
| <property name="sender" |
| value="Blueprint Greeting Service"/><br> |
| </bean><br> |
| <br> |
| <service id="greeterService"<br> |
| interface="org.apache.aries.tutorials.blueprint.greeter.api.GreeterMessageService"<br> |
| ref="serverBean"><br> |
| </service><br> |
| |
| </blueprint><br> |
| </div> |
| |
| <p>Finally, before you rebuild, you will need to edit the file:</p> |
| <div class=code>[toplevel]/source/org.apache.aries.tutorials.blueprint.greeter.server.osgi/pom.xml</div> |
| <p>and remove the line:</p> |
| <div class=code> |
| <Bundle-Activator>org.apache.aries.tutorials.blueprint.greeter.server.osgi.ServiceRegisteringActivator</Bundle-Activator> |
| </div> |
| <p>When you build and deploy the server bundle now, we should be |
| able to see it all working as expected again.</p> |
| |
| <p>Congratulations! You have completed the final step in converting |
| the greeter application to use blueprint.</p> |
| </div> |
| </body> |
| </html> |