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

4

9

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?

Enyedy answered 7/3, 2012 at 6:26 Comment(0)
P
1

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>
Pannell answered 7/3, 2012 at 6:47 Comment(2)
This is a neat trick, and I may end up going with it since I don't see us ever giving up Maven. The one down side that became immediately apparent is that developers can no longer update a JSP on the fly if it's copied out of a JAR. It takes a rebuild and redeploy from the IDE to see a simple edit. I doubt there's anything that can be done about that, but I'm all ears if you have an idea.Enyedy
Well... you could do something filthy with symlinks probably, depending on how different you're prepared to make your development environment from the final artifact. Or, if you're using an exploded WAR, it doesn't take long to run the single maven unpack goal on its own after each JSP change.Pannell
E
0

My preferred option in this cases is put all related files (controllers, js, images...) in a jar. But the problem here is the use of JSP files: there is no easy way of using them if they are in a jar. But with other view technologies such as Velocity or Freemarker this is possible in an easy way, among other advantages. I don't know if this can lead you to too much work, but for a new project with these needs it is the best option.

Emend answered 7/3, 2012 at 9:1 Comment(2)
Interesting... so you're saying we could pull Velocity/Freemarker templates from either /WEB-INF/velocity or from a JAR? Would that require a custom ViewResolver to accomplish with Spring MVC? All the examples I'm finding just refer to /WEB-INF.Enyedy
Here you have a good example: springbyexample.org/examples/velocity-email-template.htmlEmend
S
0

We are using Subversion here, and use svn:externals (kind of like symbolic links) in order to share certain common code (mostly .jsp files) between projects. Works fairly well, we were using OC4J which actually has a way to share .jsp's between multiple projects, but since we are currently moving towards Tomcat (or something else) I wanted to come up with a container agnostic way to do it.

Soda answered 20/4, 2012 at 13:33 Comment(0)
V
0

Sinuhepop is right ,but his answer not perfect.

Here is the perfect answer. you have to refer the follow url, it can hep you.

click here

in the url page, the example for the property content box is not exact, you follow me:

if need to share a file:

a.jsp  svn://myhome.com/svn/myproject/trunk/a.jsp

if need to share a folder:

xml  svn://myhome.com/svn/myproject/trunk/xml
Vociferation answered 14/3, 2013 at 8:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.