Stripes

ActionBean names from different applications conflict with each other.

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Won't Fix
  • Affects Version/s: Release 1.5.3
  • Fix Version/s: None
  • Component/s: ActionBean Dispatching
  • Labels:
    None
  • Environment:
    Tomcat 5.5, Stripes deployed as shared library.

Description

I have two applications deployed on the Tomcat server, with Stripes deployed as a shared library. Both contain ActionBeans with the same names. The name patterns are following:
net.company.app1.action.SomeActionBean
net.company.app2.action.SomeActionBean

The applications are deployed in different contexts: app1 and app2. So, the beans are accessible under following urls (relative to server root):
/app1/Some.action
/app2/Some.action

The problem is that only one of the ActionBeans are accessible at the same time. If app2 is deployed latter, its ActionBean is resolved correctly, but any request to /app1/Some.action is resolved also to /app2/Some.action. Analogical problem occurs when app1 is deployed after app2.

I found following comment in the UrlBindingFactory.addBinding() method:
"Search for a class that has already been added with the same name as the class being added now. If one is found then remove its information first and then proceed with adding it. I know this is not technically correct because two classes from two different class loaders can have the same name, but this feature is valuable for extensions that reload classes and I consider it highly unlikely to be a problem in practice."

I'm not familiar with the code enough to be sure that this design decision is a reason of the problem (however, the Tomcat uses different class loader for each application). But if so, it's also quite big limitation imposed on applications internal architecture. Maybe the context path could be also taken into account in internal structures of the dispatcher?

Activity

Hide
Ben Gunter added a comment - 21/Apr/10 7:39 AM

It seems to me that this could only be a problem if Stripes were loaded by a class loader that is shared between the two applications. That is definitely not recommended practice. Might that be the problem in your case?

Show
Ben Gunter added a comment - 21/Apr/10 7:39 AM It seems to me that this could only be a problem if Stripes were loaded by a class loader that is shared between the two applications. That is definitely not recommended practice. Might that be the problem in your case?
Hide
Aleksander Zarczynski added a comment - 21/Apr/10 9:02 AM

Thanks for such quick answer

Exactly - in my case Stripes are loaded by shared class loader. I'm not sure if you know Tomcat's class loader hierarchy? In general shared libraries are loaded by class loader which is common to all of the applications deployed on the same server, and each application has its own (additional) class loader, which loads entire stuff bundled inside a war archive.

We use Stripes as shared library intentionally. We don't want to have multiple copies of the library (inside each of the applications). In addition, we have some common libraries which also depend on Stripes, and are loaded by the shared class loader. This forces us to use Stripes also as a shared library.

Could you please explain why using Stripes as a shared library (the same class loader) is not recommended? And maybe you already have any solution for such kind of problems?

Show
Aleksander Zarczynski added a comment - 21/Apr/10 9:02 AM Thanks for such quick answer Exactly - in my case Stripes are loaded by shared class loader. I'm not sure if you know Tomcat's class loader hierarchy? In general shared libraries are loaded by class loader which is common to all of the applications deployed on the same server, and each application has its own (additional) class loader, which loads entire stuff bundled inside a war archive. We use Stripes as shared library intentionally. We don't want to have multiple copies of the library (inside each of the applications). In addition, we have some common libraries which also depend on Stripes, and are loaded by the shared class loader. This forces us to use Stripes also as a shared library. Could you please explain why using Stripes as a shared library (the same class loader) is not recommended? And maybe you already have any solution for such kind of problems?
Hide
Ben Gunter added a comment - 21/Apr/10 11:46 AM

The reason it isn't recommended is because of exactly the kind of problems you've encountered. No effort has been made to ensure the Stripes classes can be shared between applications, and I'm certain that this isn't the only problem you'll encounter by doing so. Basically, it's not something we intend to support. Your best bet is to figure out a way to use the application classloader to load Stripes.

Show
Ben Gunter added a comment - 21/Apr/10 11:46 AM The reason it isn't recommended is because of exactly the kind of problems you've encountered. No effort has been made to ensure the Stripes classes can be shared between applications, and I'm certain that this isn't the only problem you'll encounter by doing so. Basically, it's not something we intend to support. Your best bet is to figure out a way to use the application classloader to load Stripes.
Hide
Nikolaos added a comment - 18/May/10 12:20 PM

I agree with Ben on the "Won't Fix" designation of this issue and just wanted to add that although shared libraries mean one less thing to have a copy of / version and maintain in each web project it creates a pile of issues just like this one... in the MS Windows world this was referred to as "DLL Hell"... and anyone who has built a Windoze app with DLL dependencies can speak volumes to the fun that arises with shared libraries and things being there OR simply not OR the wrong versions being there!

IMO the shared libraries of a web container should be STRICTLY limited to things that absolutely NEED to be there and the only thing I can think of is something the web container itself requires but even then I haven't found a reason to do so ever with Java in my personal experience. There is some implicit beauty in the fact that a WAR can contain everything a web application needs and IMO that is were the web apps libraries should be bundled.

Now your REAL issue appears to be one of "dependency versioning". That problem has been solved. Take a look at Maven 2 especially if you have multiple projects. The learning curve is steep but once you reap its benefits / rewards I'm sure you won't be sorry.

Show
Nikolaos added a comment - 18/May/10 12:20 PM I agree with Ben on the "Won't Fix" designation of this issue and just wanted to add that although shared libraries mean one less thing to have a copy of / version and maintain in each web project it creates a pile of issues just like this one... in the MS Windows world this was referred to as "DLL Hell"... and anyone who has built a Windoze app with DLL dependencies can speak volumes to the fun that arises with shared libraries and things being there OR simply not OR the wrong versions being there! IMO the shared libraries of a web container should be STRICTLY limited to things that absolutely NEED to be there and the only thing I can think of is something the web container itself requires but even then I haven't found a reason to do so ever with Java in my personal experience. There is some implicit beauty in the fact that a WAR can contain everything a web application needs and IMO that is were the web apps libraries should be bundled. Now your REAL issue appears to be one of "dependency versioning". That problem has been solved. Take a look at Maven 2 especially if you have multiple projects. The learning curve is steep but once you reap its benefits / rewards I'm sure you won't be sorry.
Hide
Aleksander Zarczynski added a comment - 14/Jun/10 6:09 AM

Thank you for interesting remarks. However, you wrote that you hadn't found a reason for having common libraries in your personal experience. I have (maybe because my project is quite unusual). We have a lot of simple applications, which use the same database, and few common tables. So, for example, the hibernate is used as common library (to utilize common cache for all of the applications). There are also few singletons which are used by the applications, which makes them "system wide" singletons. And to achieve that they have to be put in a shared library. Do you think that shared libraries could be avoided in such a case?

Anyway, we managed to use separate copy of the Stripes per application, so it's not a problem anymore.

Show
Aleksander Zarczynski added a comment - 14/Jun/10 6:09 AM Thank you for interesting remarks. However, you wrote that you hadn't found a reason for having common libraries in your personal experience. I have (maybe because my project is quite unusual). We have a lot of simple applications, which use the same database, and few common tables. So, for example, the hibernate is used as common library (to utilize common cache for all of the applications). There are also few singletons which are used by the applications, which makes them "system wide" singletons. And to achieve that they have to be put in a shared library. Do you think that shared libraries could be avoided in such a case? Anyway, we managed to use separate copy of the Stripes per application, so it's not a problem anymore.
Hide
Nikolaos added a comment - 14/Jun/10 11:02 AM

Aleksander,

> I have (maybe because my project is quite unusual). We have a lot of simple applications, which use the same database, and few common tables. So, for example, the hibernate is used as common library (to utilize common cache for all of the applications).

Okay. So I imagine you know this... but out of box Hibernate doesn't do much to help in the case of system wide caching. Hibernates has a 1st level and 2nd level cache. in fact, OOB first level cache by default associates with the session object to eliminate duplicate transactions within the SAME session... so that is of ZERO help system wide. Second level caching can assist system wide.

So what have you configured for your Hibernate caches?

Also even if you use 2nd level caching... separate caches may in fact be more performant as cache spaces are limited and their should be less flushing of useful data (of course the compromise here is the classic speed vs. memory)... i.e. if the number of Applications is large enough and there are lots of things to cache it is not impossible that your system ends up defeating the cache it depends on due to limited resources and MANY things to cache and things getting flushed before being re-used. Of course if your caches are sufficiently large enough then no worries... but people don't always consider this potential negative outcome when not properly sizing systems and primarily focusing on the Application.

> There are also few singletons which are used by the applications, which makes them "system wide" singletons. And to achieve that they have to be put in a shared library. Do you think that shared libraries could be avoided in such a case?

Personally I do think its unnecessary... unless we are talking about some extreme case where memory may be an issue... but even then breaking out the functionality into a Services tier is what I would suggest. In fact, it sounds like what you describe is a baked-in Services tier (why do I say baked-in... read on...

I'll give you what we do today and plan on doing in the future as our Application grows:

Today we have an RP tier and 3 UI Apps (web, mobile and admin) leveraging a Service tier which makes calls through our Data Access layer and onto our DB. The services layer is simply a JAR that is bundled with each of the 3 UI Apps today. The services layer (like others) is plugged in via Spring. Yes - each web app will have its own local Service layer caches. We use multiple App server instances and multiple servers in the UI / Services layer (and will most likely leverage memched or hibernate-memcached as a caching layer).

In the future, when our App experiences growth we will move the Service tier out to another set of servers and via Spring simply wire in the stubs that make Web Service calls to the Services layer with only the addition of code and modification of Spring XML. We will use multiple App server instances and multiple servers in the UI / Services layer.

In your case, your Services tier is baked-in to the web container and spans multiple web apps through a mechanism offered by the web container. Personally I don't see the benefit of such a design and I can only envision the need for re-factoring and re-packaging of code if there is sufficient growth.

Application Architecture is obviously not black and white... but those are my views... in addition to what I have said earlier... YMMV

Show
Nikolaos added a comment - 14/Jun/10 11:02 AM Aleksander, > I have (maybe because my project is quite unusual). We have a lot of simple applications, which use the same database, and few common tables. So, for example, the hibernate is used as common library (to utilize common cache for all of the applications). Okay. So I imagine you know this... but out of box Hibernate doesn't do much to help in the case of system wide caching. Hibernates has a 1st level and 2nd level cache. in fact, OOB first level cache by default associates with the session object to eliminate duplicate transactions within the SAME session... so that is of ZERO help system wide. Second level caching can assist system wide. So what have you configured for your Hibernate caches? Also even if you use 2nd level caching... separate caches may in fact be more performant as cache spaces are limited and their should be less flushing of useful data (of course the compromise here is the classic speed vs. memory)... i.e. if the number of Applications is large enough and there are lots of things to cache it is not impossible that your system ends up defeating the cache it depends on due to limited resources and MANY things to cache and things getting flushed before being re-used. Of course if your caches are sufficiently large enough then no worries... but people don't always consider this potential negative outcome when not properly sizing systems and primarily focusing on the Application. > There are also few singletons which are used by the applications, which makes them "system wide" singletons. And to achieve that they have to be put in a shared library. Do you think that shared libraries could be avoided in such a case? Personally I do think its unnecessary... unless we are talking about some extreme case where memory may be an issue... but even then breaking out the functionality into a Services tier is what I would suggest. In fact, it sounds like what you describe is a baked-in Services tier (why do I say baked-in... read on... I'll give you what we do today and plan on doing in the future as our Application grows: Today we have an RP tier and 3 UI Apps (web, mobile and admin) leveraging a Service tier which makes calls through our Data Access layer and onto our DB. The services layer is simply a JAR that is bundled with each of the 3 UI Apps today. The services layer (like others) is plugged in via Spring. Yes - each web app will have its own local Service layer caches. We use multiple App server instances and multiple servers in the UI / Services layer (and will most likely leverage memched or hibernate-memcached as a caching layer). In the future, when our App experiences growth we will move the Service tier out to another set of servers and via Spring simply wire in the stubs that make Web Service calls to the Services layer with only the addition of code and modification of Spring XML. We will use multiple App server instances and multiple servers in the UI / Services layer. In your case, your Services tier is baked-in to the web container and spans multiple web apps through a mechanism offered by the web container. Personally I don't see the benefit of such a design and I can only envision the need for re-factoring and re-packaging of code if there is sufficient growth. Application Architecture is obviously not black and white... but those are my views... in addition to what I have said earlier... YMMV
Hide
Aleksander Zarczynski added a comment - 15/Jun/10 4:35 AM

Nikolaos,

Your remarks are very convincing. Unfortunately, in our system we have few legacy "system wide" singletons, which can't be refactored at the moment (it's rather "political" than technical limitation). But I agree that the separate services layer is much better solution. Thanks again for your answers

Show
Aleksander Zarczynski added a comment - 15/Jun/10 4:35 AM Nikolaos, Your remarks are very convincing. Unfortunately, in our system we have few legacy "system wide" singletons, which can't be refactored at the moment (it's rather "political" than technical limitation). But I agree that the separate services layer is much better solution. Thanks again for your answers

People

Vote (0)
Watch (0)

Dates

  • Created:
    21/Apr/10 7:22 AM
    Updated:
    04/Jan/11 1:29 PM
    Resolved:
    18/May/10 11:50 AM