Log4j2 JSP Taglib not working in Spring-boot Embedded Servlet Containers - spring-boot

I have a Spring boot web application which I created using the spring-boot-starter-web artifact. I am using Spring Boot Embedded Servlet Containers features to use the Tomcat embedded server. I am able to run my app in Tomcat embedded mode. I can also create a WAR file of my app and deploy it to a normal installation of Tomcat.
I have one JSP page in which I am using log4j2's JSP taglib tags. On a normal installation of Tomcat the logging from that JSP page works as expected. But when bootRun on the Tomcat embedded server I get the following error
SEVERE: Servlet.service() for servlet [jsp] in context with path [] threw exception [The absolute uri: [http://logging.apache.org/log4j/tld/log] cannot be resolved in either web.xml or the jar files deployed with this application] with root cause
org.apache.jasper.JasperException: The absolute uri: [http://logging.apache.org/log4j/tld/log] cannot be resolved in either web.xml or the jar files deployed with this application
Can this issue be solved?

The problem is occurring because Spring Boot skips log4j-*.jar by default. I've opened an issue to address this.
You can work around the problem by explicitly enabling scanning of the log4j-taglib jar. To do so, you need to add a TomcatContextCustomizer that changes the configuration of the jar scanner:
#Bean
TomcatContextCustomizer log4jTldScanningCustomizer() {
return (context) ->
((StandardJarScanFilter)context.getJarScanner().getJarScanFilter()).setTldScan("log4j-taglib*.jar");
}

Related

When starting Spring Boot Web Application in external Tomcat, I ask a question about page 404

When using Tomcat included in Boot, if a 404 error occurs, it succeeded in moving to the Custom page. However, if an external Tomcat is used, if a 404 error occurs, it will go to Tomcat's 404 page.
In situations where I can't explain tomcat's settings(For example i can't do setting error page in web.xml
), Could this issue be solved in Spring Boot?
Springboot has inbuilt tomcat server which will be started.
In following example xyz.html will work as your web.xml
#Bean
public ErrorPageRegistrar errorPage() {
return registry -> registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/xyz.html")); }

LegacyCookieProcessor in standalone Tomcat and Spring Boot [duplicate]

My code is working on tomcat 8 version 8.0.33 but on 8.5.4 i get :
An invalid domain [.mydomain] was specified for this cookie.
I have found that Rfc6265CookieProcessor is introduced in tomcat 8 latest versions.
It says on official doc that this can be reverted to LegacyCookieProcessor in context.xml but i don't know how.
Please let me know how to do this.
Thanks
You can try in context.xml
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" />
reference:
https://tomcat.apache.org/tomcat-8.0-doc/config/cookie-processor.html
Case 1: You are using Standalone Tomcat & have access to change files in tomcat server
Please follow answer by #linzkl
Case 2: You are using Standalone Tomcat but you don't have access to change files in tomcat server
Create a new file called context.xml under src/main/webapp/META-INF folder in your application & paste the content given below
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" />
</Context>
When you deploy your application in Standalone Tomcat, the context.xml file you placed under META-INF folder will override the context.xml file given in tomcat/conf/context.xml
Note: If you are following this solution, you have to do it for every single application because META-INF/context.xml is application specific
Case 3: You are using Embedded Tomcat
Create a new bean for WebServerFactoryCustomizer
#Bean
WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
return new WebServerFactoryCustomizer<TomcatServletWebServerFactory>() {
#Override
void customize(TomcatServletWebServerFactory tomcatServletWebServerFactory) {
tomcatServletWebServerFactory.addContextCustomizers(new TomcatContextCustomizer() {
#Override
public void customize(Context context) {
context.setCookieProcessor(new LegacyCookieProcessor());
}
});
}
};
}
Enabling the LegacyCookieProcessor which is used in previous versions of Tomcat has solved the problem in my application. As linzkl mentioned this is explained in Apache's website https://tomcat.apache.org/tomcat-8.0-doc/config/cookie-processor.html.
The reason is that the new version of Tomcat does not understand the . (dot) in front of the domain name of the Cookie being used.
Also, make sure to check this post when you are using Internet Explorer. Apparently, it's very likely to break.
You can find context.xml in the following path.
tomcat8/conf/context.xml
<?xml version="1.0" encoding="UTF-8”?>
<!-- The contents of this file will be loaded for each web application —>
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!-- <Manager pathname="" /> -->
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor"/>
</Context>
The problem is still with Tomcat9. Same process need to follow for Tomcat 9 to set the class.
Add the class in context.xml file.
If you are using eclipse to run the application, need to set in the context.xml file in the server folder. Refer the below screenshot for more reference.
Hope this helps someone.
SameSite issue in tomcat version < 8.5.47 has resolved
In Tomcat 8.5.47 and bellow (Tomcat 8 versions), setting CookieProcessor tag to enable same site (as given bellow) in context.xml does not work due to a bug in Tomcat.
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" sameSiteCookies="none" />
If you find in this situation where it is not a easy thing to upgrade tomcat immediately (which I faced recently), or if you find any other case where you just need custom processing in cookies; You can write your own CookieProcessor class to get around.
Please find a custom CookieProcessor implementation and details of it's deployment steps here.
In my case I wrote a custom CookieProcessor based on LegacyCookieProcessor source code that allows tomcat 8.5.47 to enable SameSite attribute in cookies.
As mentioned by #atul, this issue persists in Tomcat 9. It will most likely persist moving forward with all future versions of Tomcat, since this is the new standard.
Using the legacy cookie processor (by adding the line above to the context.xml file) is working well for us. However, the true 'fix' is to adjust how your cookie is formed in the first place. This will need to be done in your application, not in Tomcat.
The new cookie processor does not allow the domain to start with a . (dot). Adjusting your cookie (if possible) to start with a value other than that will fix this problem without reverting to the old, legacy cookie processor.
Also, it should be obvious, but I didn't see it mentioned above: after updating the context.xml file, you need to restart the Tomcat service for the change to take effect.
Cheers!

Extending ProfileImages servlet in cq5

I am trying to extend ProfileImages servlet from /libs/foundation/src/impl/src/main/java/com/day/cq/wcm/foundation/pro file/impl/ProfileImages.java
and bundling as an OSGI service.
I have the following annotations
#Component(immediate=true)
#SlingServlet(
resourceTypes = {"nt:file"},
methods = {"GET"},
selectors = {"adjust","adjust.small"},
extensions = {"res", "jpg", "png", "gif"}
)
I see my service in bundles and Services in OSGI console. However it is not doing as ProfileImages servlet used to do
ProfileImages create the thumbnail if we invoke the following URL
http://mydomain.com:4502/content/dam/geometrixx/portraits/scott_reynolds.jpg.prof.thumbnail.100.100.jpg
If my servlet is invoke, I should get the same response
http://mydomain.com:4502/content/dam/geometrixx/portraits/scott_reynolds.jpg.adjust.small.100.100.jpg
However I am getting is 404 which is from the DefaultGetServlet
It seems that Sling servet is not able to resolve my servlet
One thing I need to know is how to get my service updated in
Apache Sling Servlet Resolverorg.apache.sling.servlets.resolver
My servlet is doing the same thing as the following service in sling servlet resolver
Service ID 843 Types:
org.apache.sling.api.resource.ResourceProvider
Description: ServletResourceProvider for Servlets at
[/libs/foundation/components/primary/nt/file/prof/thumbnail.gif.servl
et, /libs/foundation/components/primary/nt/file/prof.gif.servlet,
/libs/foundation/components/primary/nt/file/prof/thumbnail.res.servle
t, /libs/foundation/components/primary/nt/file/prof.jpg.servlet,
/libs/foundation/components/primary/nt/file/prof.png.servlet,
/libs/foundation/components/primary/nt/file/prof/thumbnail.png.servle
t,
/libs/foundation/components/primary/nt/file/prof/thumbnail.jpg.servle
t, /libs/foundation/components/primary/nt/file/prof.res.servlet]
My service should be listed in sling resolver with id and something like
...../adjust.small.jpg.servlet, ..../adjust.res.servlet
I am using CRXDE web version for development
Is there any configurations I have to do to get my service in over resource resolver?
Your servlet can not be resolved because it is not registered with the Declarative Services Runtime.
The #Component and #SlingServlet annotations are not evaluated at runtime, they are part of the Apache Felix SCR Plugin Project which provides a maven plugin and ant task to create "OSGi Declarative Services" descriptors.
http://felix.apache.org/documentation/subprojects/apache-felix-maven-scr-plugin.html
For registering your Servlet as an OSGi Service an OSGI-INF/serviceComponents.xml file is required.
So I'm afraid you won't get around using a build lifecycle tool to build your OSGi bundle before uploading to CQ5, if you are planning to use the scr annotations.
Else you have to create your service component file manually.

JSP compilation issue due to JSTL validation on adding a jsp to running embedded jetty instance

I have created a JSP test framework but running into this issue if I try to add jsp to running server. The project config is as follows:
JSP is present under /webapps folder.
I create a ServletHolder dispatching to this JSP and add the servlet to webcontext.
I setup the embedded Jetty server with this webcontext and start the server
jsp page is served fine.
Now I create another ServletHolder for a different JSP and add it to running server's webcontext.
On accessing the page, I get following exception
java.lang.NullPointerException
at org.apache.taglibs.standard.tlv.JstlBaseTLV.validate(JstlBaseTLV.java:149)
at org.apache.taglibs.standard.tlv.JstlCoreTLV.validate(JstlCoreTLV.java:105)
at org.apache.jasper.compiler.TagLibraryInfoImpl.validate(TagLibraryInfoImpl.java:949)
at org.apache.jasper.compiler.Validator.validateXmlView(Validator.java:1921)
at org.apache.jasper.compiler.Validator.validate(Validator.java:1888)
at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:223)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:451)
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:625)
at org.apache.jasper.servlet.JspServletWrapper.loadTagFile(JspServletWrapper.java:280)
at org.apache.jasper.compiler.TagFileProcessor.loadTagFile(TagFileProcessor.java:660)
at org.apache.jasper.compiler.TagFileProcessor.access$000(TagFileProcessor.java:91)
at org.apache.jasper.compiler.TagFileProcessor$TagFileLoaderVisitor.visit(TagFileProcessor.java:719)
org.apache.jasper.JasperException: PWC6033: Error in Javac compilation for JSP
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:634)
Strange thing is, if I stop the webcontext and add the servlet and start webcontext again, things run fine.
I tried to debug this and found that for the second jsp/tag call to 'JstlCoreTLV.getInitParameters()' is returning null, maybe jstl is reusing the validation object from previous cache and this property is reset to null in between.
Has anyone come across this issue? would it be a bug in JSTL library?
Here is a workaround I used to fix this issue - Reinitialized the default JSP servlet to invalidate its taglib cache
ServletHolder jspServletHolder = webContext.getServletHandler()
.getServlet("jsp");
Servlet jspServlet = jspServletHolder.getServlet();
ServletConfig jspServletConfig = jspServlet.getServletConfig();
jspServlet.destroy();
jspServlet.init(jspServletConfig);

Overriding the default session manager with embedded tomcat 7 java

I am trying to override the tomcat session manager with an embedded tomcat.
These are the steps preformed in-order to load the context.xml that defines the manager entity.
..
Context context = tomcat.addWebapp(contextPath, appBase);
File configFile = new File ("D:\\context.xml");
context.setConfigFile(configFile.toURI().toURL());
tomcat.start();
..
The session manager seems to be recognized as it's constructor is being invoked but the startInternal() method is never invoked and the session manager being used is the old tomcat session manager.
The weird thing is that when defining the same configuration in a non embedded tomcat, the session manager is being overridden without problems.
Would appriciate any help on the subject.
Non embedded tomcat uses server.xml and embedded tomcat does not uses server.xml file rather we need to pass the arguments in the method.

Resources