Author: jawi
Date: Thu Apr 19 08:50:33 2012
New Revision: 1327872
URL: http://svn.apache.org/viewvc?rev=1327872&view=rev
Log:
Fixed some code highlighting problems.
Modified:
ace/site/trunk/content/dev-doc/design/ace-deployment-strategies.mdtext
Modified: ace/site/trunk/content/dev-doc/design/ace-deployment-strategies.mdtext
URL:
http://svn.apache.org/viewvc/ace/site/trunk/content/dev-doc/design/ace-deployment-strategies.mdtext?rev=1327872&r1=1327871&r2=1327872&view=diff
==============================================================================
--- ace/site/trunk/content/dev-doc/design/ace-deployment-strategies.mdtext
(original)
+++ ace/site/trunk/content/dev-doc/design/ace-deployment-strategies.mdtext Thu
Apr 19 08:50:33 2012
@@ -39,25 +39,25 @@ Another thing you can customize is wheth
To implement our own deployment strategy, we need to create a bundle that
provides the management agent with our update task. We will start with an
update task that simply prints something to the console each time it is run and
expand it later on. As can be seen in figure 1, a task is anything that
implements the `Runnable` interface, so our update task needs to do as well.
Furthermore, we will use the DependencyManager component from Felix to provide
us with the right dependent services, the most important one being the
`DeploymentService`.
The (stub) code for our update task looks like:
- #!JavaLexer
+ #!java
package net.luminis.ace.updatetask;
import org.apache.ace.deployment.service.DeploymentService;
import org.osgi.service.log.LogService;
- public class MyUpdateTask implements Runnable {
+ public class MyUpdateTask implements Runnable {
// injected by DependencyManager
- Â Â Â private DeploymentService m_service;
- Â Â Â private LogService m_logService;
-
-    public void run() {
- Â Â Â Â Â Â Â System.out.println("Hello from MyUpdateTask: " + new
java.util.Date());
- Â Â Â }
+ private DeploymentService m_service;
+ private LogService m_logService;
+
+ public void run() {
+ System.out.println("Hello from MyUpdateTask: " + new
java.util.Date());
+ }
}
The bundle activator that registers our update task as service:
- #!JavaLexer
+ #!java
package net.luminis.ace.updatetask;
import java.util.Properties;
@@ -69,7 +69,7 @@ The bundle activator that registers our
import org.osgi.framework.BundleContext;
import org.osgi.service.log.LogService;
- public class Activator extends DependencyActivatorBase {
+ public class Activator extends DependencyActivatorBase {
public void init(BundleContext context, DependencyManager manager)
throws Exception {
Properties props = new Properties();
props.put(SchedulerConstants.SCHEDULER_NAME_KEY,
MyUpdateTask.class.getName());
@@ -132,32 +132,31 @@ After startup, our update task should pr
With the boiler plating in place, its time to make our update task a little
more interesting. We change the code of our update task to the following (for
brevity, only the run() method is shown):
- #!JavaLexer
-    public void run() {
- Â Â Â Â Â Â Â try {
- Â Â Â Â Â Â Â Â Â Â Â Version local = m_service.getHighestLocalVersion();
- Â Â Â Â Â Â Â Â Â Â Â Version remote =
m_service.getHighestRemoteVersion();
-
- Â Â Â Â Â Â Â Â Â Â Â if ((remote != null) && ((local == null) ||
(remote.compareTo(local) > 0))) {
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â // Ask user whether this update should
proceed...
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â System.out.println("Update available!
Upgrade from " + local + " to " + remote + " [Y/N]?");
-
- Â Â Â Â Â Â Â Â BufferedReader reader = new BufferedReader(new
InputStreamReader(System.in));
- Â Â Â Â Â Â Â Â String result = reader.readLine();
-
- Â Â Â Â Â Â Â Â Â if ("y".equalsIgnoreCase(result)) {
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â // Ask the deployer service to
install this update...
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â m_service.installVersion(remote,
local);
-
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â
m_logService.log(LogService.LOG_INFO, "Update installed!");
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
- Â Â Â Â Â Â Â Â Â Â Â }
- Â Â Â Â Â Â Â } catch (IOException e) {
- Â Â Â Â Â Â Â Â Â Â Â m_logService.log(LogService.LOG_WARNING, "Update
failed!", e);
- Â Â Â Â Â Â Â } catch (Exception e) {
- Â Â Â Â Â Â Â Â Â Â Â m_logService.log(LogService.LOG_WARNING, "Update
failed!", e);
- Â Â Â Â Â Â Â }
-
+ #!java
+ public void run() {
+ try {
+ Version local = m_service.getHighestLocalVersion();
+ Version remote = m_service.getHighestRemoteVersion();
+
+ if ((remote != null) && ((local == null) ||
(remote.compareTo(local) > 0))) {
+ // Ask user whether this update should proceed...
+ System.out.println("Update available! Upgrade from " + local +
" to " + remote + " [Y/N]?");
+
+ BufferedReader reader = new BufferedReader(new
InputStreamReader(System.in));
+ String result = reader.readLine();
+
+ if ("y".equalsIgnoreCase(result)) {
+ // Ask the deployer service to install this update...
+ m_service.installVersion(remote, local);
+
+ m_logService.log(LogService.LOG_INFO, "Update installed!");
+ }
+ }
+ } catch (IOException e) {
+ m_logService.log(LogService.LOG_WARNING, "Update failed!", e);
+ } catch (Exception e) {
+ m_logService.log(LogService.LOG_WARNING, "Update failed!", e);
+ }
This new implementation first asks the `DeploymentService` what the current
local (= version current running on management agent) and remote (= version
available in the management server) versions are. If the remote version is
newer/higher than the local version, than we ask the user for permission to
install the update. When given, the `DeploymentService` is requested to upgrade
from the local version to the remote version.
If you would run this code, you'll notice that if the user doesn't respond
within the task's interval, a new task is started, causing an ever increasing
number of tasks to be waiting for user input in case an update is available.
Currently, due to the current implementation of ACE's scheduler, there is no
way of disabling this behavior (although it is not really difficult to resolve
this problem locally in your task).
@@ -167,45 +166,46 @@ If you would run this code, you'll notic
So far, we've reused the `DeploymentService` facade from ACE to tweak the
update process of the management agent a bit. However, there still some magic
going on in the installation of newer versions (all the logic behind
`DeploymentService#installVersion`).Â
Let's explore this method a bit more into detail. The `installVersion` method
roughly (some details are left out for brevity) has the following
implementation:
- #!JavaLexer
- Â Â Â // injected by Felix'Â dependency manager
- Â Â Â volatile Deployment m_deployer;
- Â Â Â volatile EventAdmin m_eventAdmin;
- Â Â Â volatile Identification m_identification;
- Â Â Â // denotes the host + port where ACE is listening, e.g.
http://192.168.1.1:8080/
-   final String m_host;
-
- Â Â Â /**
- Â Â Â Â * @see
org.apache.ace.deployment.service.impl.DeploymentServiceImpl#installVersion
- Â Â Â Â */
-    public void installVersion(Version highestRemoteVersion, Version
highestLocalVersion) throws Exception {
- Â Â Â Â Â Â Â InputStream inputStream = null;
- Â Â Â Â Â
- Â Â Â Â Â Â Â try {
- Â Â Â Â Â Â Â Â Â Â Â String version = highestRemoteVersion.toString();
- Â Â Â Â Â Â Â Â Â Â Â URL baseURL =Â new URL(m_host, "deployment/" +
m_identification.getID() + "/versions/");
- Â Â Â Â Â Â Â if (highestLocalVersion != null) {
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â version += "?current=" +
highestLocalVersion.toString();
- Â Â Â Â Â Â Â Â Â Â Â }
- Â Â Â Â Â Â Â Â Â Â URL dataURL = new URL(baseURL, version);
- Â Â Â Â Â Â inputStream = dataURL.openStream();
-
- Â Â Â Â Â Â Â // Post event for audit log
-       String topic = "org/apache/ace/deployment/INSTALL";
- Â Â Â Â Â Â Â Â Â Â Â m_eventAdmin.postEvent(createEvent(topic, version,
dataURL));
-
- Â Â Â Â Â Â Â Â Â Â Â m_deployer.install(inputStream);
- Â Â Â Â Â Â Â }
- Â Â Â Â Â Â Â finally {
- Â Â Â Â Â Â Â Â Â Â Â if (inputStream != null) {
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â try {
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â inputStream.close();
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â catch (Exception ex) {
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â // Not much we can do.
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
- Â Â Â Â Â Â Â Â Â Â Â }
- Â Â Â Â Â Â Â }
+ #!java
+ // injected by Felix' dependency manager
+ volatile Deployment m_deployer;
+ volatile EventAdmin m_eventAdmin;
+ volatile Identification m_identification;
+ // denotes the host + port where ACE is listening, e.g.
http://192.168.1.1:8080/
+ final String m_host;
+
+ /**
+ * @see
org.apache.ace.deployment.service.impl.DeploymentServiceImpl#installVersion
+ */
+ public void installVersion(Version highestRemoteVersion, Version
highestLocalVersion) throws Exception {
+ InputStream inputStream = null;
+
+ try {
+ String version = highestRemoteVersion.toString();
+ URL baseURL = new URL(m_host, "deployment/" +
m_identification.getID() + "/versions/");
+ if (highestLocalVersion != null) {
+ version += "?current=" + highestLocalVersion.toString();
+ }
+ URL dataURL = new URL(baseURL, version);
+ inputStream = dataURL.openStream();
+
+ // Post event for audit log
+ String topic = "org/apache/ace/deployment/INSTALL";
+ m_eventAdmin.postEvent(createEvent(topic, version, dataURL));
+
+ m_deployer.install(inputStream);
+ }
+ finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ }
+ catch (Exception ex) {
+ // Not much we can do.
+ }
+ }
+ }
+ }
Basically, the method builds up an URL to access the deployment service of
ACE. Through this URL, the deployment-service creates a deployment package
containing the changed artifacts between the given local and remote version.
The `InputStream` containing this deployment package is given to the
`Deployment` service (a facade to the standard DeploymentAdmin service) to be
installed. Note that if the installation of the deployment package fails, an
exception is thrown. As mentioned earlier, the installation of deployment
packages is done in a "all or nothing" strategy, meaning that if it fails, all
changes are reverted. For more details on this, you can read the
DeploymentAdmin specification (see [2], chapter 114).
Aside the actual installation of the deployment package, an event is also
posted to keep track of this installation. This event is picked up by the
`AuditLog` service of ACE to track all changes made to the management agent
(_one can argue whether this shouldn't be a responsibility of the Deployment
facade_).Â