Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for sharing web-tier code (Controllers and JSPs) between similar web apps

I'm working on rewriting some aging web applications. There are two in particular that are very, very similar, yet share no code today and I aim to fix that.

The projects are being rewritten with Maven, Spring MVC, and Sitemesh.

Model tier code is easy enough to share using JARs. But I don't know of any good ways to share common web-tier code (JSPs and Controllers) between similar apps.

Here's some background. These apps are webstores. One is a normal store (think amazon.com) that a user can sign into, search products, add to a shopping cart, and check out. The other is basically the same thing, only it's a punchout site. The product browse and shopping cart portions are identical. Sign in and checkout, however, are completely different.

I'm oversimplifying, but it's enough to illustrate the problem. There's a significant portion of web-tier code in the product browse and shopping cart sections that should be able to be shared between the two.

I don't think it's possible to simply have the same WAR file running as either "mode" based on an environment variable or settings from a different database. One of the differences is a completely different Spring Security config. It would also be preferable to leave the other site's sign-in and checkout controllers out of the component-scan so nobody can somehow cross over to the wrong one with URL manipulation.

I originally started using Maven Profiles and filtering to keep two different config sets (web.xml, spring configs, etc.) in the same WAR project. Based on which Maven profile is selected, the resulting WAR is built with a different config set (and a different name for clarity). This violates the Maven principal that one pom produces one artifact.

Is there a better way to do this? What about Maven WAR Overlays? I see people talking about using overlays to share common resources like CSS, JS, images, and even some common JSPs. But I don't see anyone mention sharing classes like Controllers this way.

I could push the Controller classes down to the JARs, but logically it seems they should stay with their respective JSPs. And JSPs can't also be pushed down to the JARs (right?).

I also thought about making it an EAR containing multiple WAR files -- one WAR for the common shopping experience, and another WAR for the appropriate sign-in and checkout. I believe the session can be shared between two WARs in the same EAR, but I'm not sure if it plays nice with Spring's session-scope beans. I hear they're not really stored in the session. I'd also have to figure out what to do about the Sitemesh decorators being used for the header/footer. The same Sitemesh config and its resources would need to be copied into both WARs, right? So in the end, the shopping WAR artifact would still be different in each circumstance.

I have to believe that other people have dealt with this before. Am I thinking about it the wrong way? Is there a common solution for this sort of thing?

like image 230
KevinF Avatar asked Mar 07 '12 06:03

KevinF


1 Answers

Good work doing battle against copy-paste. Why do you say it's hard to share JSPs? You can copy them out of a shared jar using the maven dependency plugin:

 <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
         <version>2.4</version>
         <executions>
           <execution>
             <id>unpack</id>
             <phase>package</phase>
             <goals>
               <goal>unpack</goal>
             </goals>
             <configuration>
               <artifactItems>
                 <artifactItem>
                   <groupId>com.example</groupId>
                   <artifactId>webapp-common</artifactId>
                   <version>1.0-SNAPSHOT</version>
                   <outputDirectory>[target jsp directory]</outputDirectory>
                   <includes>**/*.jsp</includes>
                 </artifactItem>
               </artifactItems>
             </configuration>
           </execution>
         </executions>
       </plugin>
like image 103
artbristol Avatar answered Nov 11 '22 06:11

artbristol