I have some misunderstanding of OSGI fragment,
Suppose I have deployed a bundle "B" with two classes "com.company.C1" and "com.company.C2" where C1 use C2.
And then, I deployed a fragment "F" for the host bundle "B" where F contains only one class "com.company.C2" (with a little change in the code of the first class)
Now, if the class "com.company.C1" is being executed, which class (file) "com.company.C2" will be used, from "B" or from "F" ?
Can the presence of the same class C2 twice in the same class-loader cause runtime errors (same version & differents versions)?
Read chapter "3.9.4 Overall Search Order" of OSGi Core specification and everything will be clear.
In short: The classes in the bundle are checked first and than the fragment bundle. If you have a class in the bundle and in the fragment bundle, the one in the fragment bundle will never be used.
Related
I've got a small problem (maybe it isnt even a problem)
I am making an application in Ruby, and the folder/file structure goes something like this:
OrderSet/
..item.rb
..file.rb
..order_object.rb
OrderGet/
..item.rb
..files.rb
..order.rb
As you can see I got two item.rb files, they are both different in class structure. Now I need to create an OrderSet/item.rb object, how do I specify it needs to look in OrderSet and does not get the OrderGet one?
I have to make clear, all files are required in the main rb file.
I have tried doing OrderSet.Item (the class is called Item inside the item.rb) but it complains about an ininitialized constant OrderSet
Thanks in advance!
[edit]
I have also tried to make modules out of it, maybe I don't understand the concept correctly, but I have tried it with OrderSet.Item.new (OrderSet as module name)
You could use a module to create a namespace - that way each set of classes would be encapsulated to what they do (the folder name from your example). So classes in OrderSet would be wrapped in a module for example OrderSet/item.rb would become:
module OrderSet
class Item
# methods and properties
end
end
Then you could use it like
new_order_set = OrderSet::Item.new
RubyMonk has a lesson called Modules As Namespaces which has more details and examples you can run in your browser.
I have multi-module project under SBT.
Project A (library) has reference.conf file with A's configuration parameters. Project A depends on akka-actor library, which ships with its own reference.conf file. Project A redefines some akka's parameters in own reference.conf.
Project B depends on A.
When I call ConfigFactory.load() in B, I'm getting wrong order of reference.confs merging. It first takes A's config, then applies akka-actor's config over it. Eventually, I'm getting initial akka-actor's configuration.
How can I fix it? I need to get akka-actor's config loaded first, then my A's config should be applied over it.
Ok, looks like I've found the answer in sources of ConfigFactory.
All the reference.conf is being loaded through ClassLoader.getResources. It returns java.util.Enumeration[URL]. The order of URLs in this enum is the answer to the question. So all you need to do: ensure the order of your reference.conf resources in this enumeration properly arranged.
Here is an example of how to do that. First, create your own version of ClassLoader by overriding getResources method:
import scala.collection.JavaConverters._
class CustomClassLoader(loader: ClassLoader) extends ClassLoader(loader){
override def getResources(name: String): util.Enumeration[URL] = {
val resources = super.getResources(name).asScala.toList
// arrange resources as you wish here
java.util.Collections.enumeration(resources.asJava)
}
}
Last, call load method of ConfigFactory with your CustomClassLoader instance.
Suppose there are two exported versions of an object, where both have property x but new one introduces a new property y.
How can I create bundle that can accept both versions of an object? Let's assume it will not clone objects, compare them, put into collections etc. Its interaction with object could be as simple as testing whether x != null.
Can serialization be avoided?
Osgi classloading rules are only active at classloading time. If your bundle for example publishs a service that takes an Object as parameter you can give it any instance. Even ones that come from package it does not import.
Christian is correct. To add to that, this is exactly why you should not share your objects directly, but share interfaces. Whilst that still won't make both versions of the interface available to a consumer, at least it will then try to do the right thing and choose the interface that both x and y are compatible with. In such cases, it would have to pick the lowest common denominator.
I've a test framework written in Scala+Cucumber. In the step definition classes, it loads various dependencies to Spring beans like:
class TestSteps {
val b1 = dependency("bean_b1")
When("I do xxx") {() =>
b1.doSomething()
}
}
I'd like to activate run the test in various scenarios that require the Spring context to be initialized differently and so bean_b1 would be initialized differently. I want to activate these scenarios during the steps execution and write something like:
Given I set test scenario to "scenario1"
When I do xxx
Then I should receive ZZZ
Given I set test scenario to "no_network_available"
When I do xxx
Then I should receive ConnectException
This could be resolved by launching the whole test suite with a different spring context but I need to execute the first steps with network available and then last steps with network down.
I was thinking that when dependency("...") is executed to resolve to a bean in a different Spring context(loaded based on scenario). But how to make the tests work since I have a lot of step def classes that use the "val b1 = dependency("b1_bean")" and those will remain even static no matter if dependency("b1_bean") will now return something else.
Thanks!
I'm implementing several classes which does not have data by itself, just logics. These classes implements access control policy to date which depends on several parameters taken from data from other models.
I initially try to find answer to "Where to store such classes?" here, and the answer was apps/models directory. That's ok, but I like to clearly separate these classes from ActiveRecord inherited classes in hierarchy, both as file and class.
So, I created classes inside Logic module, like Logic::EvaluationLogic or Logic::PhaseLogic. I also wanted to have constants which passed between these logics. I prefer to place these constants into Logic module too. Thus, I implemented like this:
# in logic/phase_logic.rb
module Logic
PHASE_INITIAL = 0
PHASE_MIDDLE = 1000
class PhaseLogic
def self.some_phase_control_code
end
end
end
# in logic/evaluation_logic.rb
module Logic
class EvaluationLogic
def self.some_other_code
Logic::PhaseLogic.self.some_phase_control_code(Logic::PHASE_INITIAL)
end
end
end
Now, it work just fine with rspec (It passes tests I wrote without issues), but not with development server, since it can't find the Logic::PHASE_INITIAL constant.
I suspect it's related to the mismatch of the autoloading scheme of Rails and what I wanted to do. I tried to tweak rails, but no luck, ended-up with eliminating module Logic wrap.
Now the question I want to ask: How I can organize these classes with Rails?
I'm using 3.2.1 at this moment.
Posted a follow-up question "How I can organize namespace of classes in app/modules with rails?"
I am not sure whether I really understand your classes, but couldn't you create a Logic module or (I would rather do this:) PhaseLogic and EvaluationLogic objects in /lib directory?
It is not said that "Model" is always descendant of ActiveRecord. If the object belongs to "business logic" then it is a model. You can have models which do not touch database in any way. So, if your classes are "business objects", place them in 'app/models' and use like any other model.
Another question is whether you should use inheritance or modules - but I would rather think about including a module in PhaseLogic, and not about defining PhaseLogic in a module. Of course, all this depends heavily on the intended role of your objects.
Because in Ruby the class of object is not important, you do not need to use inheritance. If you want to 'plug' the logic objects into other objects, just take care that all '*Logic' classes have the required methods. I know that all I said is very vague, but I think I cannot give you some more concrete suggestions without knowing more about the role of these objects.
Ah, and one more thing!
If you find yourself fighting with Rails class autoloading, just use the old require "lib/logic.rb" in all the classes where you are using Logic::PHASE_INITIAL constants.
In this case I suppose that your problem was caused by different order of loading. The logic/evaluation_logic.rb has been loaded before logic/phase_logic.rb. The problem may disappear if you create logic.rb somewhere, where class autoloading can find it, and define these constants in that file.
Don't name your classes or modules Logic use specific names. Start with extracting logic into separate classes and then try to break them into smaller ones. Use namespaces to distinguish them from each other in lib folder, after this steps you would be able to extract some logic parts to separate gems and reduce codebase and complexity of application. Also take a look into presenter pattern.