Is it possible to share JSPs between EARs, similar to the way that we can share Java files between EARs by using .jar files?
I have a large J2EE app on JBoss with many different EARs, and they all should have the same header, footer, etc... I would rather not copy and paste these files a dozen times whenever a change needs to be made.
Tag files can be packaged in a jar.
They are JSP files with a ".tag" extension. They can be parameterized.
I have never tried but logically speaking you can very well do it by putting all your JSP's into a common folder
I think of it as accessing a different servlet context from the one you are in. Something like
Enterprise.ear
WAR1 /somewhere
WAR2 /somewhereElse
WAR3 /shared
Assuming a JSP in WAR1 bound to /somewhere:
Reference the shared context with the optional 'context' attribute of the c:import tag (Standard JSTL tag). By default c:import uses the context it is in, which in war1 is /somewhwere.
<c:import url="/header.jsp" context="/shared"/>
There are probably other ways... Perhaps just ignore your ear and just go with a full http request:
<c:import url="http://www.somewhere.com/header.jsp"/>
I'm not certain on the syntax of the context attribute on the c:import tag. But I believe that is the correct syntax (with the slash verse without, it might not matter).
Use sitemesh.
There is no need to change anything in the existing application. Create a fresh war with sitemesh. It can decorate content from multiple urls dynamically.
http://raibledesigns.com/rd/entry/use_sitemesh_to_decorate_multiple
--Kiran.kumar
Related
I am creating a web application using Java, Spring, Hibernate and AngularJS.
but I am not clearly understand the role of WEB-INF directory. As per I know WEB-INF is a web directory where we keep our web configuration files. But I have seen some example in AngularJS app where js and html are put in WEB-INF folder and it is known that WEB-INF is not publicly accessed. So why do we put those files in WEB-INF and what actually mean of publicly accessed even when we response for a request html and js are visible to clients, and if we put in WEB-INF folder these files how to access those files.
I need some clarification on these few points before starting my app development.
Please anyone can help me regarding these issues.
As you said, we put configuration files into the WEB-INF folder. But there are cases when you use resource files (e.g. HTML templates) which are not sent to the client as-is, but usually some transformations or parameter substitution happens, which are usually handled by a Servlet.
It is ok to put such templates and resources to the WEB-INF folder because the files as are should not be visible/accessible to the clients but only the result of transformations/parameter substitutions.
Resource files are frequently stored within WEB-INF because the Java servlet container will not directly serve those files. Instead, some Java controller code is being used to serve them indirectly. This is perfectly acceptable, but I would prefer a solution that serves static content from a different server and let the Java container handle dynamic code only. In a pinch, you might just add a reverse proxy and off-load static content handling that way.
In case of Spring you can build your app without WEB-INF directory. For example: spring-boot + thymeleaf, it is possible put all html, css and js files to src/main/resources/static .. so WEB-INF directory is not necessary for all java web applications.
You don't have to use WEB-INF at all.
Here's a simple AngularJS example app (official Spring guide) on how to do this.
Now, like Elliot mentions, sometimes using proxies is a good idea (depending on the kind of traffic your application should support). You could also use a CDN, which is easier to set up and has no configuration requirement in your application.
I have recently started developing my own project from scratch using the Core of J2EE : Servlets & Jsps.
I could not evaluate whether my project folder structure is right or not. Here is my project folder structure.
The question: Is it a good sign to put my jsps outside of web-inf. If not, why is it so? If yes why?
Is there any standard folder structure convention for a J2EE web application, I know maven has brought up some standards but still, we can customize as per the requirement I believe.
What are the points to be considered while laying out the folder structure for a J2EE web application, importantly where should the Jsps, static content should go into & why?
All I can do is tell you the pros and cons to specific ideas. What follows is 100% my opinion. I don't know of any specific requirements or rules. I'm sure somebody will disagree with me.
JSP's
Let's work on whether to put JSP's in WEB-INF or not.
Pros of putting JSP's in WEB-INF:
You control how the JSP's are executed. If you want a JSP to be
parameterized and re-usable (which is really hard with a JSP anyway),
you can put them into WEB-INF and use a servlet or a Struts action
controller or some other front controller to do pre-processing and
then pass control to the JSP, passing in the right environment
context (like request attributes, any security checks, parameter
sanitation, etc.)
You can programmatically or even at a firewall or IDS level block
HTTP requests to *.jsp to reduce the likelihood of somebody uploading
a JSP to the web root and then being able to execute code as the web
server. They'd have to over-write an existing JSP. Not a huge
security gain, but it does make compromise slightly harder.
Enforces good habits, like MVC, front controller, servlet filters,
dependency injection, etc. as opposed to a big monstrous JSP that
does all the work itself and is difficult to read/maintain.
Cons of putting JSP's in WEB-INF:
You cannot access the page directly, even if it is a simple
standalone page which needs no upfront processing. This is because
files under /WEB-INF are not servable by a servlet container.
Static files
In terms of purely static files like HTML, image, stylesheet, javascript, etc. put those under the web root (my_app in your case), but NOT /WEB-INF (because it is not accessible).
Overall layout
As for the overall directory layout, it depends somewhat on your build process. I like storing everything under "src" or "source" because it makes it clear what files are generated by building and which are pure source files. main lets you separate test code like junit classes from your main source code, which is good too. But if you don't have any unit tests (oh no!), then it's a meaningless distinction.
On the other hand, if you don't manipulate the web root at all during build (like if it's all JSP and static files), then perhaps you keep it at the top level, like /webroot or /deploy and copy files in as needed, such as .class or .jar files. It is a habit of human beings (especially developers) to over-organize. A good sign of over-organizing is having lots of folders with only a single sub-folder.
What You've Shown
You've indicated that you are following a convention set by maven, so if you are already using maven, just stick with that layout. There is absolutely nothing wrong with the layout you described.
In case of WEB-INF,
If you put JSPs in WEB-INF then you won't be able to access them directly. i.e. By absolute url
Outside, WEB-INF you can directly access them
I have a web application heavily using jspx-files and jsp:include-includes which is deployed from the same jar to several hundred contexts in tomcat. Currently we can only modifying the layout of each individual instance by changing CSS or overwriting certain files in other file directories:
Let's say the webapp.jar contains a file named /css/forms.css then the webapp ensures that GETting http://mydomain/cust1/res/css/forms.css is mapped to that file. If the webapp is configured to look in the "override directory" /data/cust1/, then if there's a file named /data/cust1/css/forms.css this file is served instead from the one in the application archive. This is ensured by the webapp itself.
During the last years this has been very successful but recently I feel the pain of the restriction of the more or less static jspxs that cannot be "overridden" ;) Basically I'd like to be able to "override" some jspx files for each deployed context without compiling and deplyoing a custom webapp-jar for each context. (Having a custom something:includeJsp-tag wouldn't be a problem).
Basically the webapp should be able to provide an override to the jsp(x) compiler for individual jspx-files, e.g. take a look at the following example sutrcture:
<!-- webapp.jar:/jspx/view.jspx -->
<jsp:root ...>
<ns:customInclude src="inc/include.jspx" />
</jsp:root>
<!-- webapp.jar:/jspx/inc/include.jspx -->
<jsp:root ...>
Default-Markup from the webapp.jar
</jsp:root>
<!-- /data/cust1/jspx/inc/include.jspx -->
<jsp:root ...>
Custom markup for "cust1"
</jsp:root>
Now, when http://.../cust1/jspx/view.jspx is requested I want /data/cust1/jspx/inc/include.jspx to be compiled and executed by Tomcat.
Basically I know that actually everything necessary is already possible somewhere in Tomcat (compiling from a jspx to Java-Bytecode, including the file, ...), but I also know that Tomcat/Jasper adhere to the jsp-spec. I figured by looking at the code that this is not that easy...
So basically, does anyone know how to get a setup like this to work? Did perhaps someone already solve this? Or are there alternatives to my current approach?
I ended up implementing my own FileDirContext that is included via a <Resources>-Tag in context.xml. Actually I implemented two - an extension of org.apache.naming.resources.WARDirContext and an extension of org.apache.naming.resources.FileDirContext because I wanted to enable the same mechanisms during development with eclipse (which deploys to a file structure) and on our servers which deploy from non-exploded .war files.
Both of them can be configured via the context descriptor and can use several "virtual overlays". An overlay can either be a file system path or an external .war file (actually more like a .zip renamed to .war) or a .jar file packed into the deployed .war file.
The steps to a tuned down solution with one virtual overlay are:
Create a class MagicWARContext (magic is like the solution to every problem ;) extending from aforementioned WARDirContext.
In this class create a static inner class ProtectedMethodVisibleMaker extends FileDirContext. This allows to access certain protected methods of Tomcat's original implementation. Override doGetRealPath and doLookup.
In your own WAR context create getters and setters for a field private String overlay and a field private ProtectedMethodVisibleMaker overlayContext and instantiate a new and empty instance to this field.
In allocate() of your WAR context call overlayContext.setDocBase(overlay). Be sure to call overlayContext.release() from release() just to be sure.
Now you have to override 5 more methods of WARDirContext
doGetRealPath(String)
doLookup(String)
getAttributes(Name, String[])
list(String)
list(Name)
The resulting enumerations of both lists should of course contain entries of a virtual overlay as well as the original context. So I ended up writing my own NamingEnumeration that iterates over a list of delegate naming enumerations and ensures that each named entry is output only once.
Instantiate your Magic Context from the context descriptor:
<Resources
className="package.name.tomcatextensions.MagicWARContext"
overlay="/data/some/dir"/>
Pack your classes in a jar and copy this e.g. to tomcat/lib
Caveats
We're overriding Tomcat's internal classes. This naturally exposes this code to changes. So someone has to ensure that everything works as expected after version upgrades. Instead of some of the protected methods one can override the actual public ones, but some of them are final so you're basically out of luck.
Plus it is possible to expose non-magic subcontexts to other application layers via the lookup methods meaning they don't have that overlay anymore or don't contain the fallback resources of your deployed war. I ended up adding some warnings to the log when subcontexts are requested. During startup this happens two times, once for /WEB-INF/classes and once for /WEB-INF/lib.
In my usecase I prohibit adding virtual overlays that contain either on of those paths because I don't want to have foreign class files appearing in my web context, so this is not a problem. However some other client might be calling those methods and doing something unexpected with them. During my tests I did not find any problem, but there might occure strange effects with caching enabled or when enumerating resources and there will be problems when sub contexts are used... Of course one could create virtualized wrappers around a subcontext returned by a lookup, but I didn't do this yet as I hope this is unnecessary.
And of course this method enables you to override certain resources of the fallback webapp in un-exploding war deployments. If you just need to add external resources to the web context you can use Tomcat's aliases (see How do I add aliases to a Servlet Context in java?).
Use at your own risk and have fun.
We have a big application having 13 modules. Depending on the customer requirement, we should able to deploy core module+customer specific modules. We are planning to break the app into multiple wars. Now problem is we have some common jsp's like header.jsp, error.jsp etc. Is there any way by which we can keep the common jsp's in core war and rest of the wars will be able to use it or I have to copy these jsp's in the invidiual wars in build process. I know CSS and Javascript files can be shared across multiple wars in ear packaging but not sure about jsp's.
Good question. You'll be happy to hear that the answer is "yes", although it's highly dependent on how your servlet container is configured.
It's done using the JSTL <c:import> tag, which has an optional context attribute which is defined as:
Name of the context
(beginning with a /) of some
other local web application to
import the resource from.
So say you have webapp A deployed under context root /A, and webapp B deployed under /B, then a JSP in A can include x.jsp from B using:
<c:import context="/B" url="x.jsp"/>
This is all very nice and rosy, but this has to pass through the servlet container's security mechanism, and it may not permit the operation. For example, in Tomcat the crossContext attribute must be set to true.
I am working both in the Ruby and Java worlds. I have been inspired somewhat by the merb-assets project, which provides various functionality to make it easy to reference assets (images, CSS, etc.) located on a subdomain (or CDN).
I want to do the same in Java:
in development and testing, I want to use either JSTL's <c:url> or Struts 2's <s:url value=""/> tags to reference assets.
but in production, I want to move most of these assets out to a separate subdomain (or CDN).
Are there any taglibs (or other methodologies) out there that can help with this? I don't particular want to litter my views with <c:if and tests for localhost, everytime I insert an <img> or <link> tag.
I am using Struts 2 + JSP.
I don't really know Struts 2, but I am thinking of a solution that involves the use of Maven2 features...
So, in the case you are indeed using Maven2 to build your application, you may solve your problem with the resources filter and profiles features.
Resources filtering:
You can ask Maven2 to filter ressources files (in our case, the JSP files). Filter means to replace all ${xxx} by their value.
This will be useful to replace a parameter (${domain.url} for example) by the value you need to have ("localhost", "http://...").
Then, you define 2 profiles: "development-test" and "production".
Each profile will define its own domain for these assets. For example, in development-test, you can define the domain as "localhost", in production, the domain will be "http://....".
I am not sure if this can solve your problem, but you can give it a try :o)
References :
Filter resources: http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html
Profiles: http://maven.apache.org/guides/introduction/introduction-to-profiles.html