struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Pontarelli <br...@pontarelli.com>
Subject Re: [s2] A thought - next generation OSGi-based?
Date Sat, 26 Apr 2008 15:37:44 GMT
Don Brown wrote:
> I'll respond in more detail later, but I wanted to correct a quick
> misconception.  OSGi allows you to deploy multiple versions of the
> same API via different bundles.  No special package namespace, no
> hassles from the standpoint of the user - just declare what version
> you need and it all just works.
>
> Here is how it could look:
>
> Struts 2 -> OSGi plugin (with container) -> API impl bundles -> API bundles
>
> Therefore, multiple API versions and multiple implementations could be
> running at the same time, with OSGi hooking them together as
> appropriate.  This is only possible with OSGi.
>   
I think either I'm mis-understanding the point of this thread or you are 
mis-understanding what I feel the issue is. In either case, there is a 
disconnect. I'll jump off the thread because my main concern is still 
API compatibility and breaking compatibility at the API level can't be 
solved by a tool. This problem is a compile time problem that needs to 
be handled by developers. OSGi is a runtime dynamic loader, not a 
compile time dynamic method binder or a runtime dynamic method 
invocation layer.

-bp


> Don
>
> On Sat, Apr 26, 2008 at 3:45 AM, Brian Pontarelli <brian@pontarelli.com> wrote:
>   
>>  Ian Roughley wrote:
>>
>>     
>>> Maybe I'm overstepping my knowledge from fact, but I thought the benefit
>>>       
>> of OSGi was that you could have completely different implementations (i.e.
>> PackageConfig) running on the same JVM, with OSGi providing the classloading
>> magic so that the implementations don't collide.
>>     
>>  It actually is a compile time issue first and then later is a method
>> invocation issue and has nothing to do with OSGi. Think of it this way, you
>> have an interface:
>>
>>
>>  org.apache.struts.api.SomeInterface
>>
>>  It has two versions 1.0 and 2.0. They are very different and look like:
>>
>>  1.0
>>  ----------------------
>>  public void method1();
>>  public String method2();
>>  public Object method3(String);
>>  public Object method4(String, int);
>>
>>  2.0
>>  ----------------------
>>  public void method1();
>>  public int method2();
>>  public Object method4(int, String);
>>  public Object method5(long);
>>
>>  As you can see, method1 is the same, but the rest of it is changed
>> drastically. The issue is now that the interface is still in the same
>> package and has the same name. How do you compile against both versions?
>> Furthermore, how would OSGi be able to resolve the method invocations at
>> runtime to the two different versions?
>>
>>  Very difficult problems that I've done some work on. There isn't any good
>> solution. The only way to make it work is to follow the Java Virtual Machine
>> specifications for compatibility or implement dynamic method translation at
>> runtime. I've done that for fun to see if it works and it does, but requires
>> translators for each interface and then you have loads of more code to
>> manage and TONS of edge cases. But, it was a cool weekend project I whipped
>> up to see if it was possible using CGLIB and some other tools.
>>
>>
>>
>>     
>>> My question with Don's proposal is with item #4.  Is it new features of
>>>       
>> the same webapp that use new APIs or new webapps that use the new APIs?
>> Option one is going to be hard, and may not be possible even with OSGi.  For
>> option 2, I'm wondering if OSGi is overkill (i.e. would webapps be separated
>> enough via the container).  A better question might be is it the webapps
>> that need to change the APIs they are using, or is it the plugins?
>>     
>>  Yeah, my thoughts were along the same lines. Not sure OSGi really helps
>> that much. Here's the main case I want to cover and OSGi doesn't really
>> provide a solution:
>>
>>    You are writing something that uses Struts2 (plugin, extension, fork,
>> webapp, whatever) and want to upgrade from 2.0 to 2.1. Since traditionally
>> these are "minor" versions, the changes should be minor, meaning they should
>> be compatible. Therefore, you should be able to "just drop the JAR in the
>> classpath" and everything should work. This is the ultimate definition of
>> compatibility and something I feel Struts needs to start ensuring.
>>
>>  -bp
>>
>>
>>
>>
>>
>>     
>>> /Ian
>>>
>>> Brian Pontarelli wrote:
>>>
>>>       
>>>> Yours and mine are the same because you still have implementations
>>>>         
>> inside Struts for some of the API interfaces. For example,
>> org.apache.struts2.config.PackageProvider (yeah, I did move this from XWork
>> to Struts for my example ;), will be an API interface that applications can
>> implement. Struts2 also implements this API.
>>     
>>>> Another case is a non-interface POJO like PackageConfig. This class can
>>>>         
>> be instantiated by app1 and then passed back to struts. Likewise, app4 might
>> instantiate a different version and pass it back. You have to separate these
>> into namespaces in order to compile Struts if the versions of PackageConfig
>> are fundamentally different.
>>     
>>>> If we take the concrete example of 2.0.* and 2.1 for PackageConfig, one
>>>>         
>> is mutable, the other is immutable with the Builder pattern. However, they
>> have the same package and classname. The issue is that at compile time
>> Struts needs to import and use PackageConfig. The only way I know how to
>> pull this off is extract a common interface (Java interface that is - public
>> interface IPackageConfig) and make adapters OR to separate them into
>> namespaces.
>>     
>>>>   org.apache.struts.config.PackageConfig_2_0
>>>>   org.apache.struts.config.PackageConfig_2_1
>>>>
>>>> Then you can see the ensuing code inside Struts to deal with these:
>>>>
>>>>   org.apache.struts.config.ConfigurationManager_2_0
>>>>   org.apache.struts.config.ConfigurationManager_2_1
>>>>
>>>> And then you need some method of determining the version of the API that
>>>>         
>> the application is using and then select a configuration manager based on
>> that.
>>     
>>>> Now, there might be some type of tricks and things that OSGi can provide
>>>>         
>> to make this happen, but I'm not familiar enough with advanced bundling and
>> classloading to know how it would work. From what I understand of OSGi, any
>> bundle can only use a version of a dependent bundle that is compatible with
>> the version of that dependent bundle it compiled against.
>>     
>>>> For example, if I compiled against log4j 1.0, I can use 1.3 because they
>>>>         
>> are compatible at runtime and compile time. However, I can't use log4j 2.0
>> because the interfaces changed and things will blow up nicely at runtime.
>> What OSGi does provide is the ability to have one bundle using log4j 1.x and
>> another bundle using log4j 2.x in the same VM. I'm not aware that they have
>> gone any further than that.
>>     
>>>> Ian Roughley wrote:
>>>>
>>>>         
>>>>> Is this the case, or was the thinking more like:
>>>>>
>>>>>                                     - app 1
>>>>>                - api 1.0 --{
>>>>>               /                     - app 2
>>>>> Struts ---{
>>>>>               \                     - app 4
>>>>>                - api 2.0 --{
>>>>>                                     - app 3
>>>>>
>>>>> I think this is how I perceived it.  I also agree with Brian that
>>>>>           
>> there will be a burden on s2 to provide the necessary features for all APIs,
>> but I think it's less of a burden in this layout.
>>     
>>>>> /Ian
>>>>>
>>>>>
>>>>> Brian Pontarelli wrote:
>>>>>
>>>>>           
>>>>>> Here's a few things I think about when considering API versioning:
>>>>>>
>>>>>> 1. How many implementors are there? It sounds like there will be
one
>>>>>>             
>> - Struts2
>>     
>>>>>> 2. Do you want to allow implementors to implement multiple APIs?
>>>>>>             
>> Sounds like yes.
>>     
>>>>>> 3. How much is shared between APIs? Probably a lot.
>>>>>>
>>>>>> From what it sounds like, and correct me if I'm wrong, you are
>>>>>>             
>> looking to do something like this:
>>     
>>>>>> API 1.0----------\
>>>>>>                |----------- Struts2
>>>>>> API 2.0----------/
>>>>>>
>>>>>> If this is the case, it will require some interesting coding
>>>>>>             
>> tactics. Sun and IBM have some white papers on these types of cases. OSGi
>> will shield the two APIs from each other so there aren't any conflicts,
>> however, the implementor will have the unfortunate task of implementing
>> both. This becomes difficult without proper structure at compile time
>> because struts2 will need to implement multiple interfaces from both
>> versions and these interfaces might overlap.
>>     
>>>>>> I've done some of this type of work before and in order to truly
>>>>>>             
>> break compatibility between 1.0 and 2.0, you need namespaces in order to
>> allow Struts2 to implement both. Otherwise you get naming conflicts that
>> cannot be resolved by the compiler. I've do things like this before:
>>     
>>>>>> org.apache.struts.api1.SomeInterface
>>>>>> org.apache.struts.api2.SomeInterface
>>>>>>
>>>>>> This is the same interface, but breaks compatibility between the
API
>>>>>>             
>> versions. Only by separating the namespaces will you be able to implement
>> both at compile time. I've also worked with other situations like this:
>>     
>>>>>> org.apache.struts.api.SomeInterface_1_0
>>>>>> org.apache.struts.api.SomeInterface_2_0
>>>>>>
>>>>>> What it comes down to is that if you are going to break
>>>>>>             
>> compatibility at the API level you need to actually create a brand new API.
>> When you look at it from this perspective, OSGi really isn't needed, just
>> nice to have. Since the two API versions are in different namespaces, there
>> aren't any collisions at compile-time or runtime, eliminating the need for
>> bundle separation.
>>     
>>>>>> Having done some of these types of solutions before, I can attest
to
>>>>>>             
>> the pain that they can cause. They can also become complex to manage. Which
>> sorta leads back to my original statements about compatibility. I'd much
>> rather see something like this:
>>     
>>>>>> 1. The APIs locked down
>>>>>> 2. These APIs called Struts3
>>>>>> 3. No APIs break compatibility until Struts4
>>>>>>
>>>>>> Therefore, 3.0, 3.1, 3.2, etc are all compatible. Then when Struts4
>>>>>>             
>> start wanting to break compatibility, you branch Struts3, and start breaking
>> away on Trunk.
>>     
>>>>>> -bp
>>>>>>
>>>>>>
>>>>>>
>>>>>> Don Brown wrote:
>>>>>>
>>>>>>             
>>>>>>> As I learn more and more about OSGi, I wonder if it might be
the
>>>>>>> solution to several big problems we seem to have at the moment:
>>>>>>>               
>> poor
>>     
>>>>>>> reloadability and the lack of a solid API.  With OSGi, you can
>>>>>>>               
>> drop
>>     
>>>>>>> bundles in and out of the system at runtime, even running multiple
>>>>>>> versions of the same bundle side-by-side, but the feature I'm
most
>>>>>>> interested in right now is how it would allow us to put in a
>>>>>>>               
>> proper
>>     
>>>>>>> API while maintaining full backwards-compatibility.
>>>>>>>
>>>>>>> Evolving a web framework is hard because apps tend to be written
>>>>>>>               
>> on a
>>     
>>>>>>> specific version, and to migrate them to new versions has two
>>>>>>> problems: development may not be continuously funded and the
>>>>>>>               
>> upgrade
>>     
>>>>>>> may require too many changes to the application.  On the other
>>>>>>>               
>> hand,
>>     
>>>>>>> if you don't evolve your web framework, you quickly go out-of-date
>>>>>>>               
>> and
>>     
>>>>>>> lose interest from new developers.  In our case, despite being
a
>>>>>>> relatively new framework, we have legacy code around from 2004
>>>>>>>               
>> that we
>>     
>>>>>>> can't just remove, yet we want to provide an attractive, modern,
>>>>>>>               
>> clean
>>     
>>>>>>> framework for new development.
>>>>>>>
>>>>>>> The specific issue it hand that I've been thinking about is how
to
>>>>>>>               
>> get
>>     
>>>>>>> a proper API into Struts 2 yet keep backwards compatibility,
and I
>>>>>>> think OSGi might provide a solution.  What about this:
>>>>>>>  1. Struts 2 and its plugins remain the way they are now - 100%
>>>>>>> backwards-compatibility
>>>>>>>  2. An OSGi plugin provides the platform for the next generation
>>>>>>>               
>> of Struts 2
>>     
>>>>>>>  3. A new API bundle is created, implemented by the underlying
>>>>>>>               
>> Struts
>>     
>>>>>>> 2 framework
>>>>>>>  4. Old apps can continue to write and deploy code against Struts
>>>>>>>               
>> 2,
>>     
>>>>>>> yet new development can start to use the new API
>>>>>>>  5. Later, when we want to write API version 2, we create a new
>>>>>>>               
>> bundle
>>     
>>>>>>> that runs side-by-side the old bundle, both implemented by Struts
>>>>>>>               
>> 2
>>     
>>>>>>> Basically, OSGi would allow us to write a clean layer on top
of a
>>>>>>> framework, much like how Grails builds on Spring, but we get,
as a
>>>>>>> side benefit, all the architectural advantages of OSGi for free.
>>>>>>> Furthermore, if we do it right, users don't have to know or care
>>>>>>>               
>> that
>>     
>>>>>>> OSGi is under the hood - all they know is they write a jar, drop
>>>>>>>               
>> it in
>>     
>>>>>>> a directory or upload it via a form and they just installed part
>>>>>>>               
>> of
>>     
>>>>>>> their application at runtime.
>>>>>>>
>>>>>>> Don
>>>>>>>
>>>>>>>
>>>>>>>               
>> ---------------------------------------------------------------------
>>     
>>>>>>> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>>>>>> For additional commands, e-mail: dev-help@struts.apache.org
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>               
>>>>>>
>>>>>>             
>> ---------------------------------------------------------------------
>>     
>>>>>> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>>>>> For additional commands, e-mail: dev-help@struts.apache.org
>>>>>>
>>>>>>
>>>>>>             
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>>>> For additional commands, e-mail: dev-help@struts.apache.org
>>>>>
>>>>>
>>>>>           
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>>> For additional commands, e-mail: dev-help@struts.apache.org
>>>>
>>>>
>>>>         
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>> For additional commands, e-mail: dev-help@struts.apache.org
>>>
>>>
>>>       
>>  ---------------------------------------------------------------------
>>  To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
>>  For additional commands, e-mail: dev-help@struts.apache.org
>>
>>
>>     
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
>   


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Mime
View raw message