blob: 33d1a1f93c91d7420af4f480c6e33cfd728633e7 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="osgi.reference">
<title>Referencing an OSGi Service</title>
<para>
In an OSGi-based application, the business logic behind a controller is typically accessed through the OSGi
Service Registry.
</para>
<section id="osgi.reference.export.package">
<title>Exporting Packages</title>
<para>
By default, Bundlor detects and exports all packages in a bundle.
In this step Bundlor is told what to
export from the <literal>greenpages.app</literal> bundle and which types from those packages to use in the
<literal>greenpages.web</literal> bundle.
</para>
<para>
Add and save the following entry to the <filename>template.mf</filename> file in the
<literal>greenpages.app</literal> project and then run the <literal>MANIFEST.MF</literal> generation on the project as
explained in <xref linkend="deploy.bundle.web.module.manifest"/>.
<programlisting><![CDATA[Excluded-Exports:
greenpages.internal]]>
</programlisting>
(As before, be careful not to leave trailing spaces on the ends of lines, except for the one space after the colon,
and not to add any blank lines to the file. The second line of this entry has a leading space—do not omit it.)
</para>
<para>
Check that the package is no longer exported in the <literal>greenpages.app</literal> <literal>MANIFEST.MF</literal> file
which should look something like this:
<programlisting><![CDATA[Manifest-Version: 1.0
Bundle-Name: GreenPages Service
Bundle-ManifestVersion: 2
Bundle-SymbolicName: greenpages
Tool: Bundlor 1.0.0.RELEASE
Export-Package: greenpages;version="2.3.0"
Bundle-Version: 2.3.0]]>
</programlisting>
Go to the next step.
</para>
</section>
<section id="osgi.reference.referencing.projects.packages">
<title>Referencing Projects and Packages</title>
<para>
Now that the <literal>greenpages.app</literal> bundle exports the package that the
<interfacename>Directory</interfacename> and <interfacename>Listing</interfacename> interfaces reside in,
the <literal>greenpages.web</literal> bundle must import it.
In this step the Maven
<filename>pom.xml</filename> file is updated to depend on the <literal>greenpages.app</literal> bundle and import the
package.
</para>
<para>
Open the <filename>pom.xml</filename> file in the <literal>greenpages.web</literal> project.
(Edit the source directly by using the <literal>pom.xml</literal> tab in the editor.)
In this file add
the following entry (between the <literal><![CDATA[<dependencies>]]></literal> tags):
<programlisting language="xml"><![CDATA[<dependency>
<groupId>com.springsource.dmserver</groupId>
<artifactId>greenpages.app</artifactId>
<version>${project.version}</version>
</dependency>]]>
</programlisting>
</para>
<para>
Open the <classname>@greenpages@Controller</classname> class and import the <classname>Listing</classname> and
<classname>Directory</classname> types.
(Eclipse should now offer these as a <emphasis>Quick Fix</emphasis>.
It it does not, set <literal>greenpages.app</literal> as a project dependency of <literal>greenpages.web</literal>
in the Build Path of the web project.)
The class should now compile cleanly.
</para>
<para>
The following imports should now have been added to the <classname>@greenpages@Controller</classname> class:
<programlisting>import greenpages.Directory;
import greenpages.Listing;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
</programlisting>
</para>
<para>
Add the following package clause to the <literal>Import-Template</literal> entry in the
<filename>template.mf</filename> file in the <literal>greenpages.web</literal> project. When added run the
MANIFEST.MF generation on the project as described in <xref linkend="deploy.bundle.web.module.manifest"/>.
<programlisting><![CDATA[greenpages.*;version="[2.3, 2.4)"]]></programlisting>
Be careful to include the <quote><literal>.*</literal></quote> in the package pattern.
</para>
<para>
Once Bundlor has finished, go to the next step.
</para>
</section>
<section id="osgi.reference.deploy.par">
<title>Deploying a PAR</title>
<para>
Currently the @webserv@ instance has a single web module bundle deployed. In this step, the
<literal>greenpages.web</literal> bundle is undeployed and <literal>greenpages</literal> PAR is deployed.
</para>
<para>
Right-click on the @webserv@ in the <emphasis>Servers</emphasis> view, and select
<emphasis>Add and Remove…</emphasis>. In the dialog that opens, remove the
<literal>greenpages.web</literal> bundle and add the <literal>greenpages</literal> PAR to the server. When
the configuration is complete, press <emphasis>Finish</emphasis>.
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/web-module/add-remove-projects.png" format="PNG" align="center" width="10cm"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/web-module/add-remove-projects.png" format="PNG" align="center"/>
</imageobject>
</mediaobject>
</para>
<para>
Eclipse automatically undeploys the <literal>greenpages.web</literal> bundle and deploys the
<literal>greenpages</literal> PAR.
When this happens, the deployment may fail with an error.
If it does not, open the browser again at
<ulink url="http://localhost:8080/greenpages">http://localhost:8080/greenpages</ulink>
and observe the failure which should have a root cause similar to:
<programlisting><![CDATA[org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [greenpages.Directory] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}]]>
</programlisting>
This error is caused by there being no instance of <classname>Directory</classname> to inject into the controller.
The next section will supply one.
</para>
</section>
<section id="osgi.reference.reference">
<title>Referencing an OSGi Service</title>
<para>
There is no instance of <interfacename>Directory</interfacename> to be
injected into the controller.
In the @greenpages@ application, it is intended that this
implementation is used through an interface in
the OSGi <emphasis>Service Registry</emphasis>.
Using a service in the Service Registry enables
another bundle to
provide an implementation without revealing the implementation or the provider to all clients of the
service.
@webserv@ supports the use of the Spring DM <emphasis>namespace</emphasis> for
referencing elements in the OSGi Service Registry.
This step adds an OSGi Service Reference to an implementation of the
<interfacename>Directory</interfacename> interface.
</para>
<para>
In the <filename>webapp/WEB-INF/applicationContext.xml</filename> file in the <literal>greenpages.web</literal>
projects add a reference to a
<interfacename>greenpages.Directory</interfacename> instance in the OSGi service registry using
the <literal><![CDATA[<osgi:reference/>]]></literal> tag as follows:
<programlisting language="xml"><![CDATA[<osgi:reference id="directory" interface="greenpages.Directory"/>]]>
</programlisting>
</para>
<para>
The tools will automatically redeploy the <literal>greenpages.web</literal> bundle when the change to the
bean definition has been saved.
The web bundle will not completely start.
<!-- After some time, the following error should occur:
<programlisting><![CDATA[<CC0001W> Mandatory reference '&directory' in bundle
'greenpages-1-greenpages.web' version '2.3.0' is waiting for service with filter
'(&(objectClass=greenpages.Directory)(!(org.eclipse.virgo.server.app.name=*)))'.]]>
</programlisting> -->
</para>
<para>
This is because there is no provider of a <interfacename>greenpages.Directory</interfacename> in
the Service Registry. The next step will address this.
</para>
<para>
The error is re-issued as the @webserv@ instance waits for the service to be supplied. After about five minutes
the server will <quote>time-out</quote> and the deploy will be abandoned. This same error (and time-out)
will occur each time the PAR is redeployed as each change is made.
</para>
<para>Stop the server instance by right-clicking on the server in the <emphasis>Servers</emphasis> view and
selecting <emphasis>Stop</emphasis>. This will avoid unnecessary delays as changes are made.
</para>
</section>
</section>