Log4j configuration in jsf web app - jsf-2

The following configuration is working when I deploy the wep app in my local machine (windows)
public void contextInitialized(ServletContextEvent sce) {
Logger logger = null;
ServletContext servletContext = sce.getServletContext();
String prefix = servletContext.getRealPath("/");
String log4jFile = servletContext.getInitParameter("log4j");
if (log4jFile != null) {
DOMConfigurator.configure(prefix + log4jFile);
logger = LogManager.getLogger(StartupListener.class.getName());
logger.info("LOG4J loaded successfully: " + log4jFile);
}
}
<context-param>
<param-name>log4j</param-name>
<param-value>WEB-INF/classes/com/domain/resources/log4j.xml</param-value>
</context-param>
<listener>
<listener-class>com.domain.util.StartupListener</listener-class>
</listener>
But when installing the web app in the Linux I get the following error message:
log4j:ERROR Could not parse file [nullWEB-INF/classes/com/domain/resources/log4j.xml].
java.io.FileNotFoundException: /app/home/wdmt3/AdminServer/nullWEB-INF/classes/com/domain/resources/log4j.xml (No such file or directory)
Any advice ?

<context-param>
<param-name>log4j</param-name>
<param-value>/WEB-INF/classes/com/domain/resources/log4j.xml</param-value>
</context-param>

Problem:
servletContext.getRealPath return null and you log file path become
nullWEB-INF/classes/com/domain/resources/log4j.xml
It's impossible to load this file and log4j just throws an error message you saw.
So why servletContext.getRealPath return null?
The API docs for ServletContext.getRealPath(String path) state:
This method returns null if the servlet container is unable to translate the given virtual path to a real path.
Different container may have quite different behavior.
Solution:
Try with the solution from spring mvc and make sure log4jFile starts with '/':
String log4jFile = servletContext.getInitParameter("log4j");
String fullPath = servletContext.getRealPath(log4jFile);

The issue resolve by configure properly the weblogic server in order to retrieve the path (domain -> Web Application -> Archived Real Path Enabled)

Related

#Resource annotation not working while injecting DataSource in Tomcat Web Container

I'm developing a small Web App and using a lightweight Tomcat Web Container 8.5.4, JSF 2.2.9, and MySql.
In OrdersBean class, I am trying to use #Resource annotation to inject DataSource
#ManagedBean(name="orders")
#SessionScoped
public class OrdersBean {
//resource injection
#Resource(name="jdbc/tcomdb")
private DataSource ds;
public List<Orders> getOrderList() throws SQLException {
if(ds == null)
throw new SQLException("Cannot retrieve Data Source ds");
//get database connection
Connection con = ds.getConnection();
//...
}
However Tomcat Web Container is not injecting datasource and throwing NullPointerException.
But if I try to get DataSource object in a traditional way by context lookup service it works perfectly.
//resource injection not working, getting manually.
public OrdersBean() {
try {
Context ctx = new InitialContext();
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/tcomdb");
} catch (NamingException e) {
e.printStackTrace();
}
}
web.xml
<resource-ref>
<description>MySQL Datasource example</description>
<res-ref-name>jdbc/tcomdb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<!-- JSF mapping -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
MySql DataSource configuration in context.xml
<Context>
<Resource name="jdbc/tcomdb" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="root" password="passwd" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/tcomdb"/>
</Context>
I suppose dependency injection works in Tomcat Web Container since release of ver. 6 / 7 as seen in the changelog : http://tomcat.apache.org/tomcat-7.0-doc/changelog.html
Can anyone confirm ? If Tomcat does support then whats going wrong in my code / config ?
Also I want to know how tomcat web container works internally to create DataSource object in both cases: Dependency Injection and Context Lookup?
Please explain.

payara glassfish web xml filter url parsing

I have kind of below filter mapping my web xml. But the deployment fails. Is there an alternative ? thanks
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping> <!-- this works -->
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/Application/*.html</url-pattern>
</filter-mapping> <!-- this doesn't work with parsing error as below-->
Error
java.lang.IllegalArgumentException: Invalid URL Pattern: [{0}]
at org.glassfish.web.deployment.node.WebResourceCollectionNode.setElementValue(WebResourceCollectionNode.java:136)
at com.sun.enterprise.deployment.node.SaxParserHandler.endElement(SaxParserHandler.java:583)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
I'm afraid that mixing mapping by suffix and prefix, as in /Application/*.html isn't supported. You need to map with one of the following patterns:
/Application/* (everything with /Application prefix will be mapped)
/*.html (everything with the html suffix will be mapped)
If you want to mix them together, you can map by the prefix (the first option) to a proxy servlet, which would parse the URL in the request and forward it to the appropriate servlet with ServletContext.html#getNamedDispatcher and forward(req, resp), like this for a servlet named application-html:
if (request.getRequestURI().endsWith(".html")) {
request.getServletContext()
.getNamedDispatcher("application-html")
.forward(request, response)
}

Unable to perform JNDI lookup using IBM WebSphere Application Server Liberty

I am using IBM WebSphere Application Server Liberty to perform JNDI lookup.I am pretty sure about giving right about the location of resources in the project. However, when i run this I am getting a name not found error.
Here is the code performing the lookup:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
PrintWriter out = response.getWriter();
response.setContentType("text/html");
try {
FlightService flightService = (FlightService)new InitialContext().lookup("java:comp/Web1/FlightService!com.airline.FlightService");
}
catch(Exception ex){
ex.printStackTrace();
}
if(flightService !=null){
out.println(flightService.getAirplaneModel());
out.println(flightService.getFrom());
out.println(flightService.getTo());
}
}
Here is the server.xml:
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>webProfile-7.0</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint httpPort="9090" httpsPort="9443" id="defaultHttpEndpoint"/>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>
<webApplication id="Web1" location="Web1-0.0.1-SNAPSHOT.war" name="Web1"/>
</server>
I am not sure , If i have to set any configuration related properties. Any help would be appreciated.
Looking at the server xml. I don't see JNDI entry being defined.
Based on the code, it should be trying to access a JNDI entry from a servlet. In this case, where do you define you JNDI entry in the first place?
I think you need the following to define the JNDI entry in the server xml
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_8.5.5/com.ibm.websphere.wlp.doc/ae/twlp_dep_jndi_refentry.html
Please give it a try

OAuth2ClientContext (spring-security-oauth2) not persisted in Redis when using spring-session and spring-cloud-security

Thanks a lot in advance for reading this question.
Setup
I am using:
spring-security-oauth2:2.0.7.RELEASE
spring-cloud-security:1.0.1.RELEASE
spring-session:1.0.1.RELEASE
and would have a question regarding the persistence of spring-security-oauth2 OAuth2ClientContext in a Redis datastore when using spring-session (via #EnableRedisHttpSession) in a Single-Sign-On (#EnableOAuth2Sso), reverse proxy (#EnableZuulProxy) gateway.
Problem
It seems to me that the SessionScoped JdkDynamicAopProxied DefaultOAuth2ClientContext created in org.springframework.cloud.security.oauth2.client.OAuth2ClientAutoConfiguration is not correctly persisted in the Redis datastore.
#Configuration
#ConditionalOnBean(OAuth2SsoConfiguration.class)
#ConditionalOnWebApplication
protected abstract static class SessionScopedConfiguration extends BaseConfiguration {
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2ClientContext oauth2ClientContext() {
return new DefaultOAuth2ClientContext(accessTokenRequest);
}
}
Debugging the creation of the oauth2ClientContext without #EnableRedisHttpSession shows that (as expected) the bean will be instantiated once per client session and stored in the HttpSession. This instance will then be reused to store the fetched OAuth2 bearerToken details in addition to storing the OAuth2 accessToken in Spring SecurityContext's org.springframework.security.core.Authentication.
However, once using #EnableRedisHttpSession, the oauth2ClientContext bean will be first created on the session creation but also later on (while still using the same client session). Debugging the Redis client session content confirms that oauth2ClientContext is not correctly being persisted by session creation:
Before we retrieve the OAuth2 bearerToken (NO SpringContext, NO scopedTarget.oauth2ClientContext):
~$ redis-cli hkeys "spring:session:sessions:17c5e80b-390c-4fd6-b5f9-a6f225dbe8ea"
1) "maxInactiveInterval"
2) "sessionAttr:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"
3) "lastAccessedTime"
4) "creationTime"
5) "sessionAttr:SPRING_SECURITY_SAVED_REQUEST"
After we retrieved the OAuth2 bearerToken (SpringContext persisted, but NO scopedTarget.oauth2ClientContext):
~$ redis-cli hkeys "spring:session:sessions:844ca2c4-ef2f-43eb-b867-ca6b88025c8b"
1) "sessionAttr:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"
2) "lastAccessedTime"
3) "creationTime"
4) "sessionAttr:SPRING_SECURITY_LAST_EXCEPTION"
5) "sessionAttr:SPRING_SECURITY_CONTEXT"
6) "maxInactiveInterval"
If we now try to access one of the configurer Zuul's routes (therefore requiring to call org.springframework.security.oauth2.client.DefaultOAuth2ClientContext#getAccessToken), another instance of oauth2ClientContext will be created (since not persisted in Redis, with a null AccessToken.
Funnily enough, this instance will later be persisted in Redis (but a null instance is persisted since the AccessToken is not re-asked for):
~$ redis-cli hkeys "spring:session:sessions:c7120835-6709-4c03-8d2c-98f830ed6104"
1) "sessionAttr:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"
2) "sessionAttr:SPRING_SECURITY_LAST_EXCEPTION"
3) "sessionAttr:scopedTarget.oauth2ClientContext"
4) "sessionAttr:SPRING_SECURITY_CONTEXT"
5) "maxInactiveInterval"
6) "creationTime"
7) "lastAccessedTime"
8) "sessionAttr:org.springframework.web.context.request.ServletRequestAttributes.DESTRUCTION_CALLBACK.scopedTarget.oauth2ClientContext"
Creating a Simple ScopedProxyMode.TARGET_CLASS Injected bean worked as expected however with the bean being persisted correctly in Redis.
public class HelloWorldService implements Serializable {
public HelloWorldService(){
System.out.println("HelloWorldService created");
}
private String name = "World";
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public String getHelloMessage() {
return "Hello " + this.name;
}
}
#Configuration
public class AppConfig {
private SecureRandom random = new SecureRandom();
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloWorldService myHelloService(){
HelloWorldService s = new HelloWorldService();
String name = new BigInteger(130, random).toString(32);
System.out.println("name = " + name);
s.setName(name);
System.out.println("Resource HelloWorldService created = " + s);
return s;
}
}
Example
The described problem can be reproduced in #dave-syer example for an OAuth2 reverse proxy gateway by adding the following dependencies:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
as well as the #EnableRedisHttpSession annotation in UiApplication.
Question
Should we ignore org.springframework.cloud.security.oauth2.client.OAuth2ClientAutoConfiguration from AutoConfiguration and manually create a oauth2ClientContext with a different setup to enable spring-session persistence in Redis? If so, can you please provide an example?
Otherwise: how to persist oauth2ClientContext in Redis?
Many in advance to anyone reading this question an trying to help.
There's a known issue there (https://github.com/spring-projects/spring-session/issues/129 and https://github.com/spring-projects/spring-boot/issues/2637). You can work around it by adding a RequestContextFilter.
#dave-syer hint was correct.
I post here the configuration which can be used to setup the RequestContextFilter and enable spring-session persistence of spring-security-oauth objects. In case this can help someone...
#Configuration
public class RequestContextFilterConfiguration {
#Bean
#ConditionalOnMissingBean(RequestContextFilter.class)
public RequestContextFilter requestContextFilter() {
return new RequestContextFilter();
}
#Bean
public FilterRegistrationBean requestContextFilterChainRegistration(
#Qualifier("requestContextFilter") Filter securityFilter) {
FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
registration.setOrder(SessionRepositoryFilter.DEFAULT_ORDER + 1);
registration.setName("requestContextFilter");
return registration;
}
}
I came across this post and I have the exact same issue with some minor differences:
my application is not a Spring Boot application
I use JDBC persistence instead of Redis
However, and this might save some hours of future readers, the above solution also worked for me. Since I'm not using Spring Boot, I'll publish the solution here to be applied in a non Spring Boot application using web.xml configuration.
The "trick" is to define in the web.xml the RequestContextFilter. As far as my testing goes I have not seen any border effects of having both the request context filter living aside the request context listener.
What is important is the ordering of the filters. You need to define the filters in this order in your web.xml:
session repository filter
request context filter
security filter
So something like:
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
If this helps you save a few hours of digging into Stackoverflow and other web sites, it makes my day.

Injecting Stateless Local EJB (3.1) into #WebComponent in WebLogic 12c not working

I have a Java EE 6 War project containing the following:
An EJB declared as so (it's also a JAX-RS Service):
#Path("/booksList")
#Produces("application/json")
#Stateless
#LocalBean
#Local(BooksListEJB.class)
public class BooksListEJBImpl implements BooksListEJB
A WebComponent declared as so:
#WebServlet(urlPatterns="/initDbData")
public class DataInitListener extends HttpServlet {
#EJB
private BooksListEJB booksListEJB;
An empty beans.xml file in the WEB-INF folder
When I deploy it in WebLogic 12c, I get the following error:
<Warning> <weblogic.jaxrs.onwls.deploy.ejb.provider.EJBComponentProviderFactory> <BEA-000000> <An instance of EJB class com.shivandragon.jee6TestService.ejb.impl.BooksListEJBImpl could not be looked up using simple form name. Attempting to look up using the fully-qualified form name.
javax.naming.NameNotFoundException: While trying to look up comp/env/BooksListEJBImpl in /app/webapp/jee6Test-service-0.1-SNAPSHOT.war/2039754748.; remaining na
me 'comp/env/BooksListEJBImpl'
at weblogic.jndi.internal.BasicNamingNode.newNameNotFoundException(BasicNamingNode.java:1180)
at weblogic.jndi.internal.ApplicationNamingNode.lookup(ApplicationNamingNode.java:146)
at weblogic.jndi.internal.WLEventContextImpl.lookup(WLEventContextImpl.java:253)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:426)
at weblogic.jndi.factories.java.ReadOnlyContextWrapper.lookup(ReadOnlyContextWrapper.java:45)
Truncated. see log file for complete stacktrace
I've looked similar questions, and found the suggestion to add #ManagedBean to the servlet. Tried that but had the same error.
My question is:
Shouldn't this work, am I misusing some Java EE 6 directive/standard?
In EJB 3.1 have been added new Bean view - LocaBean. You can develop a bean without need implement any inerfaces. That beans view is "no-interface view", annotated with #LocalBean and injected by classname. There are beans that implemented some local interfaces and has "local view" and should be injected via local interface. In your code you mixed no-interface view bean and local view bean. You should delete the #LocalBean annotation as #Sam answered.
Updated
I test it on WebLogic Server 12.1.1.0.
Create a simple interface with one method:
package ejbrest;
public interface SessionEJBLocal {
public String hello();
}
Then create a EJB with the RESTful annotations:
package ejbrest;
// ... imports
#Path("/booksList")
#Produces("application/json")
#Stateless
#Local(SessionEJBLocal.class)
public class SessionEJBBean implements SessionEJBLocal {
public SessionEJBBean() {
}
#Override
#GET
public String hello() {
return "Hello, world";
}
}
The deployment descriptor, web.xml (you can see it does not have any servlet definitions):
<?xml version = '1.0' encoding = 'UTF-8'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>
You can create a servlet for the local bean injection demo:
package ejbrest;
// ... imports
#WebServlet(name = "DemoServlet", urlPatterns = { "/demoservlet" })
public class DemoServlet extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=UTF-8";
#EJB
private SessionEJBLocal ejb;
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>DemoServlet</title></head>");
out.println("<body>");
out.println("<p>The servlet has received a GET. This is the reply: " +
ejb.hello() + "</p>");
out.println("</body></html>");
out.close();
}
}
After deployment you can try call your RESTful service by url:
http://[host]:[port]/[appcontext]/resources/booksList
Response:
Hello, world
Also, your demo servlet will be accessable by url:
http://[host]:[port]/[appcontext]/demoservlet
Response:
The servlet has received a GET. This is the reply:Hello, world
By default Oracle WebLogic Server use resources as link on Jersey servlet. Please read the official documentation for informs about all supported deployments variants.

Resources