Liferay Delegate Servlet cannot access liferay utility beans - java

I am trying to build a delegate servlet in Liferay that needs to know the list of connected users in Liferay (using com.liferay.portal.service.UserLocalServiceUtil)
I had no problem getting a simple delegated servlet to work and say Hello when deployed in Liferay, but when I try to use UserLocalServiceUtil I get this exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'com.liferay.portal.service.UserLocalService' is defined
Reading docs it seems that a delegate server could access core portal utilities, but could I be wrong. Any help or advice will be appreciated.
This is the servlet
package mycompany.liferay;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.service.UserServiceUtil;
import com.liferay.portal.model.User;
import java.util.List;
public class myDelegateServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>My delegate Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>My delegate Servlet at " + request.getContextPath() + "</h1>");
int userCount = UserLocalServiceUtil.getUsersCount();
List<User> users = UserLocalServiceUtil.getUsers(0, userCount);
out.print("<br>Connected Users:<br>");
for (User user : users)
{
out.print("<li>User: "+user.getUserId()+"</li>" );
}
out.println("</body>");
out.println("</html>");
}
catch (Exception e)
{
out.print("Exception! "+e.getMessage() );
}
finally {
out.close();
}
}
...
and this its definition at web.xml
<servlet>
<servlet-name>myDelegateServlet</servlet-name>
<servlet-class>com.liferay.portal.kernel.servlet.PortalDelegateServlet</servlet-class>
<init-param>
<param-name>servlet-class</param-name>
<param-value>mycompany.liferay.myDelegateServlet</param-value>
</init-param>
<init-param>
<param-name>sub-context</param-name>
<param-value>myDelegateServlet</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Have a look at this sample servlet. https://github.com/liferay/liferay-blade-samples/tree/master/gradle/extensions/servlet. The approach that you mentioned is more for the 6.2 version.
Then when you have the OSGi component you can easily inject services.
#Reference
private UserLocalService servcie;
You need to have the dependency org.osgi:org.osgi.service.component.annotations:1.3.0
Alternatively have a look at the JAX-RS interface

Related

Could not load user defined filter in web.xml: com.xxx.CORSFilter

I have a SpringBoot application running on WebLogic Server Version: 12.2.1.3.0
When I define a custom servlet Filter its working fine on Embedded Tomcat. However, when i deploy my application as a war file to wlserver it throws following error after each request. What am i missing here?
<Could not load user defined filter in web.xml: com.thy.bwsadmin.CORSFilter.
java.lang.AbstractMethodError
at weblogic.servlet.internal.FilterManager$FilterInitAction.run(FilterManager.java:400)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:328)
at weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197)
at weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71)
at weblogic.servlet.internal.FilterManager.initFilter(FilterManager.java:130)
at weblogic.servlet.internal.FilterManager.loadFilter(FilterManager.java:92)
at weblogic.servlet.internal.FilterManager.preloadFilters(FilterManager.java:72)
at weblogic.servlet.internal.WebAppServletContext.preloadResources(WebAppServletContext.java:1928)
at weblogic.servlet.internal.WebAppServletContext.start(WebAppServletContext.java:3106)
at weblogic.servlet.internal.WebAppModule.startContexts(WebAppModule.java:1843)
at weblogic.servlet.internal.WebAppModule.start(WebAppModule.java:884)
at weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:360)
at weblogic.application.internal.ExtensibleModuleWrapper$StartStateChange.next(ExtensibleModuleWrapper.java:356)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
at weblogic.application.internal.ExtensibleModuleWrapper.start(ExtensibleModuleWrapper.java:138)
at weblogic.application.internal.flow.ModuleListenerInvoker.start(ModuleListenerInvoker.java:124)
at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:233)
at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:228)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
at weblogic.application.internal.flow.ModuleStateDriver.start(ModuleStateDriver.java:78)
at weblogic.application.internal.flow.StartModulesFlow.activate(StartModulesFlow.java:52)
at weblogic.application.internal.BaseDeployment$2.next(BaseDeployment.java:752)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
at weblogic.application.internal.BaseDeployment.activate(BaseDeployment.java:262)
This is the content of my web.xml file
<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">
<display-name>MWSAdminService</display-name>
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>com.sample.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
I am setting servlet dependency as provided to prevent jar conflicts.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
This is my Filter class.
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.thy.bwsadmin.service.SecurityUserService;
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {
#Autowired
SecurityUserService securityUserService;
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
boolean isAuthenticated = authenticateUser(request.getHeader("identity_no"), request.getRequestURI());
if (isAuthenticated) {
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
} else {
response.sendError(HttpServletResponse.SC_OK, "401");
}
}
private boolean authenticateUser(String userId, String requestURI) {
if (Util.isNotEmpty(userId)
&& securityUserService.isAuthorizedForEndpoint(userId.trim(), requestURI)) {
return true;
}else{
return false;
}
}
}
As a solution i tried to remove the filter definitions in web.xml file and registered my filter as a bean configuration since this is a SpringBoot application. I also removed #Component and #Order annotations from my filter.
But the result was the same as above. It is still working on Tomcat but not in Weblogic. Here is the code for filter config bean.
#Configuration
public class Filters {
#Bean
public FilterRegistrationBean<CORSFilter> loggingFilter() {
FilterRegistrationBean<CORSFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new CORSFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
Your servlet api provided by weblogic is probably old version and your filter class needs to override init method.
Add below code at your filter class;
#Override
public void init(FilterConfig filterConfig) throws ServletException {};
At new versions of servlet api, filter class has default empty init method.

javax.servlet.UnavailableException: SRVE0200E - Maven webapp

I am trying to deploy a single maven webapp on a Websphere Liberty Server.
My code (XCCQuery.java):
package TTAQuery;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Response;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
#WebServlet(name="XCCQuery", urlPatterns={"/hello"})
public class XCCQuery extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String simpleParam = getServletConfig().getInitParameter("simpleParam");
out.println("Hello World "+simpleParam);
out.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
My web.xml looks like this:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>XCCQuery</servlet-name>
<display-name>XCCQuery</display-name>
<description></description>
<servlet-class>XCCQuery</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XCCQuery</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
I try to access:
http://localhost:9087/XCCQueryServlet/rest/hello
but always get:
Error 404: javax.servlet.UnavailableException: SRVE0200E: Servlet [XCCQuery]: Could not find required class - XCCQuery
Seems to be a deployment mistake for me.
What's wrong here?

Jersey filter registration via web xml not working

I have a filter which should validate Ids of incoming requests if the resource it is send to is annotated with IdValidation.
I tried to add this filter in the web xml as described in this tutorial. However the filter is not invoked when testing a method with the IdValidation annotation.
#Provider
#IdValidation
public class IdValidationFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
this.requestContext = requestContext;
MultivaluedMap<String, String> map = requestContext.getUriInfo().getPathParameters();
if (map.containsKey("someId")) {
// Do some validation and abort if nessecary
}
}
}
The interface I use to add this filter.
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
public #interface IdValidation {}
The web xml. I tried without the provider classnames at first because I think this is not necessary since the filter is in the same package, but this didn't work either.
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>my.package.IdValidationFilter</param-value>
</init-param>
</servlet>
try this code -
import java.io.IOException;
import java.lang.annotation.Annotation;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
#Provider
public class IdValidationFilter implements ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
#Context
private HttpServletRequest request;
#Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
for (Annotation annotation : resourceInfo.getResourceMethod().getDeclaredAnnotations()) {
if (IdValidation.class == annotation.annotationType()) {
this.requestContext = requestContext;
MultivaluedMap<String, String> map = requestContext.getUriInfo().getPathParameters();
if (map.containsKey("someId")) {
// Do some validation and abort if nessecary
}
}
}
}
}
If you want to validate a parameter, I suggest you should have a look at Jersey's Bean Validation support.

HTTP Status Code 404 Java/Servlets

Even though I found several similar questions I'm not able to create my first Hello World Servlet. I keep receiving status code 404.
So in the following folder /home/smihai/apache-tomcat-7.0.52/webapps/HelloWorld/WEB-INF/ I have a web.xml file and another folder "classes" with 2 files: HelloWorld.java and HelloWorld.class.
The web.xml file contains:
<web-app>
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
</web-app>
The HelloWorld.java contains:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException{
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
pw.println("<html>");
pw.println("<head><title>Hello World</title></title>");
pw.println("<body>");
pw.println("<h1>Hello World</h1>");
pw.println("</body></html>");
}
}
What am I doing wrong?
You would need to put/move your HelloWorld.java class inside a package.
URL would be: localhost:8080/HelloWorld/HelloWorld
Folder Structure:
HelloWorld.java:
package servlets;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class HelloWorld
*/
public class HelloWorld extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public HelloWorld() {
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
pw.println("<html>");
pw.println("<head><title>Hello World</title></title>");
pw.println("<body>");
pw.println("<h1>Hello World</h1>");
pw.println("</body></html>");
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Servlet-Mapping:
<servlet>
<description></description>
<display-name>HelloWorld</display-name>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>servlets.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
URL:

Counting the number of users in web App in servlet

I have modified my application to find out the number of users logged in a web application below is my piece of code..
the listener class
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class SessionCounter implements HttpSessionListener
{
private static int count;
public static int getActiveSessions() {
return count;
}
public SessionCounter()
{
}
//The "sessionCount" attribute which has been set in the servletContext should not be modified in any other part of the application.
//Since we are using serveltContext in both the methods to modify the same variable, we have synchronized it for consistency.
public void sessionCreated(HttpSessionEvent e)
{
count++;
ServletContext sContext = e.getSession().getServletContext();
synchronized (sContext)
{
sContext.setAttribute("sessionCount", new Integer(count));
}
}
public void sessionDestroyed(HttpSessionEvent e)
{
count--;
ServletContext sContext = e.getSession().getServletContext();
synchronized (sContext)
{
sContext.setAttribute("sessionCount", new Integer(count));
}
}
}
and the main servlet is ..
package com.saral;
import java.io.IOException;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class First
*/
//#WebServlet("/First")
public class MyServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
static final Logger logger = Logger.getLogger(MyServlet.class);
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PropertyConfigurator.configure("log4j.properties");
logger.info("before---->");
// TODO Auto-generated method stub
String name=request.getParameter("txtName");
response.setContentType("text/html");
PrintWriter out=response.getWriter();
out.println("Hello,"+name);
out.println("<br> this output is generated by a simple servlet.");
out.println("Total Number of users logged in--->"+SessionCounter.getActiveSessions());
out.close();
}
}
and the web.xml is ...
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>FirstDemo</display-name>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.saral.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>home.html</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.saral.SessionCounter</listener-class>
</listener>
</web-app>
but I am getting the total number of users logged in as 0 , which is not perfect, please advise where I am wrong and how can I overcome from this.
When a client request come to the Tomcat server and you don't call request.getSession(), then the Tomcat server stil creates a session automatically. After that, the method sessionCreated(...) in your SessionCounter class is called.
The method sessionDestroyed(...) will be called when a session is destroyed. That occurs when you call session.invalidate(). If you close a tab on browser or close a browser, the session is still alive on your tomcat server.
I think so. You can use some diffrent listeners to archive your goal: HttpSessionAttributeListener, HttpSessionBindingListener,...

Categories

Resources