Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 454015 - Duplicate bundles deployed into Virgo Server by Virgo Tools
Summary: Duplicate bundles deployed into Virgo Server by Virgo Tools
Status: RESOLVED FIXED
Alias: None
Product: Virgo
Classification: RT
Component: tooling (show other bugs)
Version: unspecified   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 1.0.2.RELEASE   Edit
Assignee: Florian Waibel CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 407855 (view as bug list)
Depends on:
Blocks:
 
Reported: 2014-12-03 08:56 EST by GianMaria Romanato CLA
Modified: 2015-08-10 02:17 EDT (History)
2 users (show)

See Also:


Attachments
Work in progress patch for review (3.53 KB, application/x-zip-compressed)
2015-06-22 04:42 EDT, GianMaria Romanato CLA
no flags Details
Work in progress patch for review - version 2 (6.10 KB, application/x-zip-compressed)
2015-06-23 08:46 EDT, GianMaria Romanato CLA
no flags Details
Work in progress patch for review - version 3 (6.36 KB, application/x-zip-compressed)
2015-06-24 08:27 EDT, GianMaria Romanato CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description GianMaria Romanato CLA 2014-12-03 08:56:59 EST
For deploying bundles in your Eclipse workspace to the Virgo test environment, the Virgo tools use a stage directory that is configured as a watched repository for Virgo.

If you then create a server instance using Virgo tools and add to the server a number of bundles, in the wrong dependency order, the Virgo tools may deploy the same bundle twice.

This happens for example if you have three bundles, A, B, C where C depends on B which in turn depends on A:    C -> B -> A.

Once you add A,B,C to the server via Virgo tools, they get copied to the stage directory that is a watched repository.

Now, if by mistake you configure the bundle order in the server editor as A,C,B instead of A,B,C you will get C duplicated. This is because upon startup A will be resolved, installed, started, then C will be resolved installed and started. Now, since C depends on B amd B is contained in the stage directory which is a watched repository, Virgo will implicitly resolve B and activate it as it is a required dependency of C. 

This is perfectly fine behavior but the problem is that the fact that B is also listed in the startup order after C will make the tools install another B in Virgo. 

The OSGi console will then show two B, with same symbolic name and version but different bunlde ID.

The system should rather silently ignore the second B or just interrupt deployment with an exception.

This subtle bug is difficult to track in large applications. It typically does not result in wrong wirings, but it fools extenders.

Workaround: fix the order in which bundles should be activated.
Comment 1 GianMaria Romanato CLA 2014-12-03 08:59:16 EST
There is a mistake in my previous comment. It's B that gets duplicated, but the first time I uncorrectly wrote C:

"Now, if by mistake you configure the bundle order in the server editor as A,C,B instead of A,B,C you will get C duplicated."  should have been "Now, if by mistake you configure the bundle order in the server editor as A,C,B instead of A,B,C you will get B duplicated."
Comment 2 GianMaria Romanato CLA 2015-05-22 07:22:28 EDT
*** Bug 407855 has been marked as a duplicate of this bug. ***
Comment 3 Florian Waibel CLA 2015-05-22 08:15:04 EDT
Thank you for clarification.
Comment 4 GianMaria Romanato CLA 2015-05-22 11:43:34 EDT
I think that a possible solution to this problem could be implemented in 

   org.eclipse.virgo.ide.runtime.internal.core.DefaultServerDeployer.deploy(IModule...)

by checking if the same IModule (version and symbolic name) is already deployed on the server before deploying it.

I hope to have some time to investigate a bit more over the next week.
Comment 5 Florian Waibel CLA 2015-05-22 11:45:09 EDT
That would be great. I'm looking forward to your contribution.
Comment 6 GianMaria Romanato CLA 2015-06-17 03:35:46 EDT
Florian, could you point me to a how-to for properly setting up a workspace for Virgo-Ide development?

I tried as follows:

- clone the git repository org.eclipse.virgo.ide
- File -> Import Existing Maven Projects  and select 
  org.eclipse.virgo.ide/pom.xml
- switch to the Luna test drive branch (I am on luna)

As this did not compile properly, I tried the "SuggestedTargetPlatform.target" but I still experience compile errors related to SWT.
Comment 7 Florian Waibel CLA 2015-06-17 05:03:01 EDT
I experience compile errors in the project: "org.eclipse.virgo.ide.ui.tests" related to SWTBot. Are you refering to these errors? I never used SWTBot on my own and didn't have time to research how to compile and run those tests locally.
Comment 8 Florian Waibel CLA 2015-06-17 05:41:14 EDT
I added SWTBot to my Eclipse installation and fixed the suggested target platform to contain the missing org.hamcrest.core.

Now my workspace is compile clean on branch "luna_testdrive".

HTH,
  florian
Comment 9 GianMaria Romanato CLA 2015-06-17 07:52:53 EDT
Thanks Florian, 

no, I am not worried about SWTBot. 
Looks like Eclipse  is not properly setting up the "plugin dependencies" container in the project classpath. The SWT bundle is there, but the O.S. specific part is not (in my case, the GTK 64bit implementation as I am using Ubuntu 12.04), so all references to org.eclipse.swt lead to compiler errors. 

I'll try again with a fresh Eclipse installation.
Comment 10 GianMaria Romanato CLA 2015-06-17 08:47:42 EDT
Got it, the target platform was specifying Mac OS. Sorry, I did not notice it.
Comment 11 Florian Waibel CLA 2015-06-17 08:55:00 EDT
That's most probably my fault.

Sorry for any inconvenience caused. I will remove this constraint from the target definition(s).
Comment 12 GianMaria Romanato CLA 2015-06-18 04:26:19 EDT
Sorry for this rather long comment, I think I found two ways to address this problem, and would need some advice about which one is the best/preferred.

My workspace now compiles properly, although I cannot manage to have a working launch configuration due to many duplicate singleton bundles in the target platform. In any case this is not an issue, I can build and remotely debug.

To recap, the source of the problem is that:
- when you add bundles to the Virgo runtime, the Virgo IDE creates a stage   
  directory as a watched repository (the launch configuration passes to the 
  runtime a custom repository configuration file created on the fly) and when 
  you perform the publish operation bundles get copied into the stage directory
- if you add bundles to the Virgo runtime in the wrong order, some bundles may 
  be installed, resolved and started twice because (i) they get started the 
  first time as a dependency of some other bundle deployed to the Virgo runtime 
  by the IDE (because they are found in a repository directory) and (ii) they get 
  started a second time by the IDE tools because they have been added to the  
  Virgo runtime in the IDE

Apparently, when deployed in this way, Virgo does not check that a bundle is 
already existing (same symbolic name, same version and same install location) 
and it gets deployed and started twice, which fools OSGi extenders and leads
to issues difficult to track.

I guess all of this originates from the fact that the stage directory is configured as a bundle repository, so a wrong artefact order may pass unnoticed and lead to this issue. If instead of doing this the Virgo IDE did configure the stage directory as a repository, the problem would not show up, but I bet there are good reasons that I ignore for configuring the stage folder as a repository folder.

So my proposal is that I modify the JmxServerDeployCommand so that before deploying an IModule (which represents a bundle deployed on the Virgo Runtime via the IDE) it checks whether the same bundle is already deployed or not.

The check can be done via the Virgo server JMX beans in two ways:
a. by enquiring via JMX the user region bean for the list of all deployed bundles 
   and iterating over such list to check whether the bundle which is about to 
   be deployed is already present or not
b. by trying to locate and enquiry via JMX a bean named after the bundle, because
   it seems that Virgo creates a JMX bean for each deployed bundle (under the
   ArtifactModel "folder")

The second options seems cleaner and probably more efficient to me, but I would
appreciate some advice from the Virgo committers.

Note that the IModel instance that the JmxServerDeployCommand receives for
each bundle contains the symbolic name, install location and the IProject but not the bundle version. I believe I should use the symbolic name and install location (which is a path within the stage folder) for checking. I don't think that parsing the IProject MANIFEST for obtaining the version is a good idea, because the IProject in the 
workspace may contain unpublished changes.

Now, whichever the JMX enquiry, I can either 
1. modify directly JmxServerDeployCommand to perform the enquiry and simply an skip
   already deployed IModule
2. create a new dedicated JMX command for that purpose which will be used by the
   deploy command and modify the ServerBehaviour class (if I remember correctly)
   to provide a new factory method for it, as for all other commands. This seems 
   more congruent with the current implementation, but is also more invasive.

So here are my questions:
- which is the most appropriate approach for obtaining the information I need
  from the runtime (a) or (b). If it's the same I will go for (b).
- which ever the selected approach (a) and (b), I will need to create a JMX 
  ObjectName to obtain the bean. Are the constants enumerated somewhere? I could 
  not find them.
- In which way would you prefer the change to be implemented (1) or (2)?
- the above has been verified with Virgo 3.6. I can imagine that this will work
  also with 3.5 but I never used earlier versions of Virgo. Are the JMX beans 
  avaialable also in 2.x or should I simply perform the check if the server 
  version is >=3.5, also considering the 2.x is pretty old?
- are there coding conventions, formatting preferencese etc I should comply with?

Thanks.
Comment 13 Florian Waibel CLA 2015-06-19 04:36:26 EDT
Given the fact that you are more familiar with this code than I am I'd say it is up to you to decide which option to choose. Please find my 2 cent inline.

- which is the most appropriate approach for obtaining the information I need
  from the runtime (a) or (b). If it's the same I will go for (b).

I'd prefer (b) - the option without looping.

- which ever the selected approach (a) and (b), I will need to create a JMX 
  ObjectName to obtain the bean. Are the constants enumerated somewhere? I could 
  not find them.

Which JMX ObjectName are you refering to?

There are some constants in the package: org.osgi.jmx.framework.

public interface BundleStateMBean {
	/**
	 * The Object Name prefix for this mbean. The full object name also contains
	 * the framework name and uuid as properties.
	 */
	String			OBJECTNAME					= JmxConstants.OSGI_CORE + ":type=bundleState,version=1.7";

Is this what you are looking for?

- In which way would you prefer the change to be implemented (1) or (2)?

As stated above I'd leave it up to you to choose.

- the above has been verified with Virgo 3.6. I can imagine that this will work
  also with 3.5 but I never used earlier versions of Virgo. Are the JMX beans 
  avaialable also in 2.x or should I simply perform the check if the server 
  version is >=3.5, also considering the 2.x is pretty old?

Implementing this for 3.5+ only seems pragmatically to me.

- are there coding conventions, formatting preferencese etc I should comply with?

Yes. Please have a look at our Wiki: https://wiki.eclipse.org/Virgo/Committers/Coding
Comment 14 GianMaria Romanato CLA 2015-06-19 06:43:05 EDT
In relation to JMX, via the Eclipse debugger I found out that to obtain the JMX bean created by Virgo for a deployed bundle named "org.example.bundle" I must perform the following JMX call:

ObjecName name = 
    ObjectName.getInstance("org.eclipse.virgo.kernel:type=ArtifactModel,artifacttype=bundle,version=*,region=org.eclipse.virgo.region.user,name=org.example.bundle");


Set<ObjectInstance> objects = jmxConnection.queryMBeans(name);


So I was wondering whether some one from the server runtime team could confirm that I can trust the "org.eclipse.virgo.kernel" JMX domain to always contain a bean for an already deployed bundle and if there are constants declared somewhere for the key/value pairs (folders) I must specify in the object name, e.g. "type=ArtifactModel" and "artifacttype=bundle".

Thanks.
GianMaria.
Comment 15 Florian Waibel CLA 2015-06-19 06:55:07 EDT
No, not to my knowledge.

A widespread "pattern" in the runtime code is something like:

    private static final String OBJECT_NAME_PATTERN = "%s:type=Repository,name=%s";

    /**
     * Creates a uniform object name based on the name of the repository
     * 
     * @param mBeanDomain the domain name to use
     * @param repositoryName The name of the repository
     * @return The uniform object name
     * @throws NullPointerException but this should never happen
     * @throws MalformedObjectNameException if the generated object name would be badly formed
     */
    public static ObjectName createObjectName(String mBeanDomain, String repositoryName) throws MalformedObjectNameException, NullPointerException {
        return new ObjectName(String.format(OBJECT_NAME_PATTERN, mBeanDomain, repositoryName));


We might consider introducing something like "org.eclipse.virgo.util.jmx.ObjectNameBuilder".
Perhaps in oev.util.jmx?

What do you think?
Comment 16 GianMaria Romanato CLA 2015-06-22 04:10:05 EDT
In principle I don't like constant classes for "specification" constants, e.g. "HTTP" "GET" "POST" etc., because those strings are not going to change in the future, and listing them in a constants class often has the side effect of  leading to a code base where many other classes refer to the constants class, sometimes to the point that unnecessary dependencies between packages (or even worse bundles) may be introduced.

I was asking for constants worried that the JMX internals of the Virgo Server may be changed and the IDE may remain out of sync. However, after more careful thinking, I can imagine that the MBean names used by Virgo are a sort of "SPI" and I believe that they are not subject to frequent changes from on Virgo version to another. Plus, a quick search for ObjectName in the code base reveals that all occurrences are located in the org.eclipse.virgo.ide.runtime.internal.core.command package within the Jmx* classes, so I guess there is very low risk that something is forgotten or left out if a refactoring is needed due to changes in a future runtime version.

Given that the Mars release is due this week, I believe it should give more value to end users to have a working Virgo IDE out as soon as possible, so I would suggest to postpone refactorings to a later time,  maybe to the SR1.
Comment 17 GianMaria Romanato CLA 2015-06-22 04:42:10 EDT
Created attachment 254598 [details]
Work in progress patch for review
Comment 18 GianMaria Romanato CLA 2015-06-22 05:04:51 EDT
I attached a work in progress patch for review.

The patch is quite simple:
- JmxServerDeployCommand is changed so that before deploying an IModule (bundle)
  it invokes another command to check whether the same bundle is already
  deployed or not
- JmxServerCheckBundleDeployedCommand is the command used to check whether a 
  given IModule is already deployed or not

As I don't think JmxServerCheckBundleDeployedCommand is that reusable, I propose to initially make it a class with default visibility, that will be used by JmxServerDeployCommand only. Therefore I will not to modify IServerRuntimeProvider to add a factory method for creating JmxServerCheckBundleDeployedCommand instances.

Comments:
- The MBean created by Virgo for each deployed bundle under the ArtifactModel 
  domain contains the bundle symbolic name and version but not the install 
  location. To the contrary, the IModule contains the symbolic name and the
  IProject and can be used to derive the install location but the version is 
  missing. 
- To verify that the bundle to be deployed is already deployed or not, I am
  parsing the MANIFEST.MF of the IModule given its install location, and
  enquiring the ArtifactModel with that version. Parsing the MANIFEST.MF
  and calling the JMX bean has no noticeable performance effect on my 3 years   
  old Lenovo thinkpad running Ubuntu 12.04. Still, I'll try to postpone the
  MANIFEST.MF parsing and execute if and only if the ArtifactModel contains at
  least one bundle with the given symbolic name.
- As already written in other comments, I am parsing the MANIFEST in the 
  install location (stage folder) and not the one in the IProject as the
  IProject may contain unpublished changes.
- There is a farily simple error management: should the check fail
  in any way, the result of the check will be "bundle not already deployed" and 
  Virgo IDE will therefore behave like it did without this patch.
- This patch solves the problem described by this bugzilla entry but has a 
  consequence. If the user workspace contains bundle A and B, where B depends  
  on A but the user configures the artifact order so that B appears before A,
  when starting B Virgo will also start A. In this case, it will log in the   
  server console that B is installed and started while there will be no log 
  statement about A which will be silently resolved and started as it happens
  for any other bundle in the bundle repository. 
  So the user may be confused by the fact that the server is
  started but there is not log entry about bundle A, despite being it added to
  the server instance. A check via the OSGi console will however reveal that A 
  has been resolved/started. Without this patch, the log line will be there but 
  the container will contain two instances of A. As I cannot control from the 
  IDE the server log, I could only open a popup at the and of the deploy to
  warn the user about the misconfiguration, but this looks clumsy to me. So I 
  would rather do nothing.

Still to do:
- apply the correct formatting preferences and coding conventions 
- use the same approach for the ObjectName constant as used in the runtime and 
  suggested by Florian
- use a differnt ObjectName for Virgo 2.x
- evaluate the feasibility of postponing MANIFEST.MF parsing
- change the source code comment with something more appropriate (I copied the 
  header from another source and it now contains SpringSource as the copyright 
  owner, but what is the correct header now that the project organization has
  changed?
Comment 19 GianMaria Romanato CLA 2015-06-23 08:46:51 EDT
Created attachment 254640 [details]
Work in progress patch for review - version 2
Comment 20 GianMaria Romanato CLA 2015-06-23 08:50:52 EDT
I attached a new revision of the patch

Done:
- use an ObjectName constant that mimics the suggestion from Florian
- postponed MANIFEST.MF parsing

Still to do:
- apply the correct formatting preferences and coding conventions 
- change the source code comment with something more appropriate (I copied the 
  header from another source and it now contains SpringSource as the copyright 
  owner, but what is the correct header now that the project organization has
  changed?
- use a different ObjectName for Virgo 2.x, if needed.


I added a new constructor the JmxServerDeployCommand which accepts a boolean to enable the "already deployed check" and override the factory method in the Virgo 3.5 provider to use such constructor so that the check is activated.
Comment 21 GianMaria Romanato CLA 2015-06-24 08:27:24 EDT
Created attachment 254667 [details]
Work in progress patch for review - version 3
Comment 22 GianMaria Romanato CLA 2015-06-24 08:34:20 EDT
Here is an additional revision of the patch.

The main improvement is that now, besides checking that a bundle is already deployed, the code also verifies that it is in ACTIVE state and if not it starts the bundle.

In all my tests, implicitly deployed bundles were always ACTIVE, but a colleague of mine pointed out that a bundle in an OSGi repository may remain in resolved state, and that would be inconsistent with the standard behaviour of the Virgo IDE which always starts the bundles it deploys.
Comment 23 GianMaria Romanato CLA 2015-07-29 11:06:19 EDT
Hi, 

any feedback? Meanwhile I have been using the patch on my workstation  without experiencing any side effect.
Comment 24 Florian Waibel CLA 2015-08-06 08:02:51 EDT
Setting target milestone to 1.0.1.RELEASE.
Comment 25 GianMaria Romanato CLA 2015-08-06 08:20:18 EDT
Hi Florian,

I see you are pretty busy, do you want me to make the patch a pull request on github? Maybe that will save you some time.

GianMaria.
Comment 26 Florian Waibel CLA 2015-08-06 08:49:47 EDT
No, that's not necessary. Thanks for the offer. I already applied the patch locally for review.

I was a bit puzzled by the name "Work in progress...". Do you intend to add something?
Comment 27 Florian Waibel CLA 2015-08-06 09:54:11 EDT
I was able to reproduce the issue with latest Virgo IDE:

128	ACTIVE      a_1.0.0
129	ACTIVE      c_1.0.0
130	ACTIVE      b_1.0.0
131	ACTIVE      b_1.0.0
Comment 28 Florian Waibel CLA 2015-08-06 10:00:45 EDT
With the patch applied I can see that only three bundles are deployed:

125	ACTIVE      a_1.0.0
...
130	ACTIVE      c_1.0.0
131	ACTIVE      b_1.0.0
Comment 29 Florian Waibel CLA 2015-08-06 10:24:44 EDT
Pushed with [fbea140] to master.

 * Fixed copyright header of new file.
 * Fixed a typo

Thanks for your contribution.
Comment 30 GianMaria Romanato CLA 2015-08-07 03:30:12 EDT
Hi Florian,

sorry for not being able to help you out yesterday, I was on leave, but I am glad you were able to reproduce the issue by yourself.

With respect to WIP, I was waiting for your review and the correct copyright header, so again thank you for your fix.

GianMaria.
Comment 31 Florian Waibel CLA 2015-08-10 02:17:23 EDT
Changed Target Milstone to 1.0.2.RELEASE.
@GianMaria Thanks for spotting this.