Tomcat 8.5/RHEL Session Replication Manager | Session Attribute value will not be replicated - tomcat8

I have an unusual "bug". I've configured Tomcat Session Replication Manager (Delta). The SessionID and Session attributes are replicated, but not the content of the attributes.
my cluster-tag in server.xml
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="6">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4001"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
../webapps/ROOT/WEB-INF/web.xml on all other machines:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<display-name>Welcome to Tomcat</display-name>
<description>
Welcome to Tomcat
</description>
<distributable/>
</web-app>
../webapps/ROOT/index.jsp for all instances (1, 2, .. )
<%#page import="java.util.ArrayList"%>
<%#page import="java.util.Date"%>
<%#page import="java.util.List"%>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%# page import="javax.servlet.http.HttpUtils.*" %>
<!DOCTYPE html>
<html>
<style type="text/css">
th {
font-weight:bold;
text-align:left;
}
</style>
<head>
<meta http-equiv="Content-Type" content"text/html"; charset=UTF-8">
<title> JSP PAGE </title>
</head>
<body>
<FONT size = 5 COLOR="#0000FF">
Instance 1 <br/> <br/>
</FONT>
<hr/>
<br/>
<table cellpadding="10" >
<tr> <th> Session Id </th> <td> <%=request.getSession().getId()%> </td> </tr>
<tr> <th> Is it New Session </th> <td> <%=request.getSession().isNew()%> </td> </tr>
<tr> <th> Session Create Date </th> <td> <%=new Date(request.getSession().getCreationTime())%> </td> </tr>
<tr> <th> Session Access Date </th> <td> <%=new Date(request.getSession().getLastAccessedTime())%> </td> </tr>
</table>
<br/><br/><br/><br/>
<b> Cart List </b> <br/>
<hr/>
<ul>
<%
String bookName = request.getParameter("bookName");
List<String> listOfBooks = (List<String>) request.getSession().getAttribute("Books");
if (listOfBooks == null) {
listOfBooks = new ArrayList<String>();
request.getSession().setAttribute("Books", listOfBooks);
}
if (bookName != null) {
listOfBooks.add(bookName);
}
for (String book : listOfBooks ) {
out.println("<li>"+book + "</li>");
}
%>
</ul>
<form action="index.jsp" method="POST" >
<input type= "text" name="bookName" placeholder="Enter bookname" required />
<input type = "submit" value = "add to cart" > <br/>
</form>
Result after adding some session attributes/values via index.jsp
on INSTANCE1 (Primary)
on INSTANCE2 (Backup) (Attributes will not be replicated!)
In the log files I see that the instances recognize each other and
send signals. But
when I send ping -t 1 -c 2 228.0.0.4, I get following:
2 packets transmitted, 0 received, 100% packet loss, time 5852ms
Why are the SessionID and Attribute replicated, but not the value of the Attribute?

I was finally able to solve this problem, and nobody, not even the official java documentation helped when I typed keywords, which is a DISGRACE in the world of documentation!!!!!! You see, I don't think java has an out-of-the-box way to notify the other instances whenever the contents of a list change. There is no DatasetChangedNotify method to notify the other tomcat instances that the list contents have been changed, only if a session attribute itself is changed.
That's right. I know you're following Ramki's tutorial; so am I. Don't follow the nutty suggestions you find on the internet because they don't work; I've tried them. Follow Ramki's tutorial EXACTLY; whatever he does on the video, you do it, BUT CHANGE your JSP scriptlet to:
String bookName = request.getParameter("bookName");
List<String> listOfBooks = (ArrayList<String>) request.getSession().getAttribute("Books");
if(listOfBooks == null) {
listOfBooks = new ArrayList<String>();
}
if(bookName != null) {
listOfBooks.add(bookName);
}
request.getSession().setAttribute("Books", listOfBooks);
for(String book: listOfBooks) {
out.println("<li>" + book + "</li><br />");
}
You've probably understood it by now, but in case someone else needs more assistance, this is what's happening: in the tutorial, Ramki sets the listOfBooks as the object to the Books session attribute only at the beginning. It should be setting it every time.
Whenever the setAttribute method is called, all the tomcat instances will get notified that the session attribute with the name Books has been changed and, if it's a list, the list will get scanned, so all instances will know the contents have been changed and will display them. Don't worry that you'll always be setting the Books attribute over itself because it'll just be overwritten.
If setAttribute is only called once, whenever listOfBooks is null, when the list is changed, only the tomcat instance that's running the scriptlet will be notified and act accordingly with respect to the session attribute, but all the other instances won't rescan the list they have in their Books session attributes, so their lists are still empty to them.
That's why you're having a full list in the first instance, but all the other instances have an empty list.

Related

ADD PortletResource permission for specific users to VIEW custom portlet PROGRAMATICALLY

I want my custom portlet to be view-able by specific users but they're ALL MEMBERS OF SAME GROUP/SITE.
i.e...
User 1: my custom Portlet is not view-able
Admin: my custom portlet is view-able
User 2: my custom portlet is view-able
How to ADD Portlet-Resource permission for particular user to VIEW custom portlet PROGRAMATICALLY in my Jsp???
Here's my code..
<%#page import="com.liferay.portal.security.permission.ActionKeys"%>
<%#page import="com.liferay.portal.security.permission.PermissionChecker"%>
<%#page import="com.liferay.portal.model.Permission"%>
<%# taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%# page import="com.liferay.portal.theme.ThemeDisplay" %>
<%# page import="com.liferay.portal.kernel.util.WebKeys" %>
<%# taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%#page import="com.liferay.portal.service.RoleLocalServiceUtil"%>
<%#page import="com.liferay.portal.service.UserLocalServiceUtil"%>
<portlet:defineObjects />
<theme:defineObjects/>
<% ThemeDisplay themeDisplay = ThemeDisplay)request.getAttribute(WebKeys.THEME_DISPLAY);
PermissionChecker permissionChecker = themeDisplay.getPermissionChecker();
long companyId = themeDisplay.getCompanyId();
long roleId = RoleLocalServiceUtil.getRole(companyId, "Administrator").getRoleId();
long userId = themeDisplay.getUserId();
UserLocalServiceUtil.hasRoleUser(roleId, userId);
if(permissionChecker.hasPermission(roleId, "com.test.sokbu", 10162, ActionKeys.VIEW)){System.out.println("Ok!");}%>
Thank you in advance!
Best Regards,
Cjohn
I just followed this link http://agile-reflections.opnworks.com/2011/07/experimenting-with-liferay-permissions.html and viola! it's now working! =) Thanks to Sir Laurent Gauthier
THIS IS MY SAMPLE.
STEP 1
Create a resource-actions folder inside docroot/WEB-INF/src
Create perm.xml
<?xml version='1.0' encoding='UTF-8'?>
<resource-action-mapping>
<portlet-resource>
<portlet-name>permissions</portlet-name>
<permissions>
<supports>
<action-key>VIEW</action-key>
<!-- <action-key>DELETE</action-key> -->
</supports>
<site-member-defaults>
<!-- <action-key>VIEW</action-key> -->
<!-- <action-key>DELETE</action-key> -->
</site-member-defaults>
<guest-defaults>
<!-- <action-key>VIEW</action-key> -->
</guest-defaults>
<guest-unsupported>
<action-key>VIEW</action-key>
</guest-unsupported>
</permissions>
</portlet-resource>
</resource-action-mapping>
Create default.xml
<?xml version="1.0"?>
<resource-action-mapping>
<resource file="resource-actions/perm.xml" />
</resource-action-mapping>
STEP 2
- Create a file named portlet.properties inside docroot/WEB-INF/src
- Insert this.. resource.actions.configs=resource-actions/default.xml
STEP 3
- Insert <add-default-resource>true</add-default-resource> after </css-class-wrapper> tag in liferay-portlet.xml.
STEP 4
Here I followed what's on the blog of Sir Laurent..
Open a browser on your Liferay instance as Liferay administrator
Create a new role named "Example Role"
Create a new user named "Example User" and set the user's password
Assign the "Example Role" to the newly created user
Open a different browser on your Liferay instance so as to have a different session, log in as "Example User" and navigate to the page containing this portlet
Pls Note
Whenever I have changes in perm.xml, I restart my server for changes to take effect.

Spring Webflow - IllegalStateException when using multipart/form-data and file upload

I am trying to add file upload to my Spring Webflog form processing. As far as the form enctype is not set to multipart/form-data, form submition works just fine. But after I added enctype="multipart/form-data" to my Spring form, this Exception occurs:
java.lang.IllegalStateException: A flow execution action URL can only be obtained in a RenderRequest or a ResourceRequest
at org.springframework.webflow.context.portlet.PortletExternalContext.getFlowExecutionUrl(PortletExternalContext.java:215)
at org.springframework.webflow.engine.impl.RequestControlContextImpl.getFlowExecutionUrl(RequestControlContextImpl.java:178)
at org.springframework.webflow.mvc.view.AbstractMvcView.render(AbstractMvcView.java:189)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:293)
at org.springframework.webflow.engine.ViewState.refresh(ViewState.java:242)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:220)
at org.springframework.webflow.engine.Flow.resume(Flow.java:537)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.portlet.FlowHandlerAdapter.handleAction(FlowHandlerAdapter.java:161)
at org.springframework.web.portlet.DispatcherPortlet.doActionService(DispatcherPortlet.java:670)
at org.springframework.web.portlet.FrameworkPortlet.processRequest(FrameworkPortlet.java:520)
at org.springframework.web.portlet.FrameworkPortlet.processAction(FrameworkPortlet.java:461)
at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:71)
I have added CommonsMultipartResolver to my spring context:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- Limit uploads to one byte smaller than the server is allowed to handle -->
<property name="maxUploadSize" value="100000" />
</bean>
and have commons-fileupload.jar in my pom.xml:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
My JSP looks like this:
<portlet:actionURL var="processFormAction" >
<portlet:param name="execution" value="${flowExecutionKey}"/>
</portlet:actionURL>
<form:form action="${processFormAction}" modelAttribute="customerModel" enctype="multipart/form-data" method="post" >
<form:input path="firstName" cssClass="input-size-1 valid-required" />
<form:input path="lastName" cssClass="input-size-1 valid-required" />
<input name="avatar" id="avatar" type="file"/>
<input type="submit" name="_eventId_submit" id="send" value="Submit"/>
</form:form>
My flow.xml definition:
<view-state id="state1" model="customerModel">
...
<transition on="submit" to="submitFormActions"/>
</view-state>
<action-state id="submitFormActions">
<evaluate expression="portletAction.processForm(customerModel, flowRequestContext)" />
<transition on="success" to="state2"/>
<transition on="error" to="state1" />
</action-state>
The model object:
public class CustomerModel implements Serializable{
private String firstName;
private String lastName;
private MutlipartFile avatar;
...
//public getters and setters
}
Any thoughts what could be wrong? As I said, without enctype="multipart/form-data" the form processing works well.
Thanks
You are using org.springframework.web.multipart.commons.CommonsMultipartResolver which is not aware about the portlet context.
You need to change CommonsMultipartResolver to:
<bean id="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
Also, for this bean to be recognised by DispatcherPortlet, you need to define this bean id as mentioned above. The doc says:
Any configured PortletMultipartResolver bean must have the following id (or name): "portletMultipartResolver".
If you have defined your PortletMultipartResolver with any other name, then the DispatcherPortlet will not
find your PortletMultipartResolver, and consequently no multipart support will be in effect.

java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/sql/SQLExecutionTag

I'm getting an error when I'm trying to run a JSP file with some JSTL tags specially SQL in it... in Tomcat server.
I can make out.. it clearly says, some problems with SQL but here what i have in my code.;
<%# page language="java" contentType="text/html; charset=ISO-8859-1"%>
<%# taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<sql:setDataSource dataSource="EMS_DataSource" />
<sql:query var="qryGet" >
SELECT ems_emp_id, ems_emp_fname, ems_emp_lname FROM riz_ems_emp
</sql:query>
<c:forEach var="row" items="${qryGet.rows}">
<tr>
<td><c:out value="${row.ems_emp_id}" /></td>
<td><c:out value="${row.ems_emp_fname}" /></td>
<td><c:out value="${row.ems_emp_lname}" /></td>
</tr>
</c:forEach>
Apart from this, I have correctly closed all my relevant tags.
Someone Please tell me the reason for this error.
NOW: I changed my jars to jsp-api-2.0.jar and jstl-1.2.jar.
now the error i get is ;
Unable to compile class for JSP: The method getELContext() is
undefined for the type PageContext
You are overriding the values for the default database configuration . You should provide your datasource in the <sql:query> tag as,
<sql:setDataSource var=dbDetails dataSource="EMS_DataSource" />
<sql:query dataSource=${dbDetails } var="qryGet" >
SELECT ems_emp_id, ems_emp_fname, ems_emp_lname FROM riz_ems_emp
</sql:query>
Also make sure you have specified the enough attributes for the sql:setDataSource tag.
Hope this helps !!

Passing value from Default.aspx to App or Main page in silverlight3

I'm using silverlight3 and vb.net..I want to pass the value from Default.aspx to my App or Main page. I wrote the code in my default.aspx page which it is returning the local ip address of the client System, I would like that same address to be used in my silverlight pages.
VB code
Dim clientIPAddress = System.Net.Dns
.GetHostAddresses(strHostName).GetValue(0).ToString()
This clientIPAddress will get the local ip of the client which is like 192.168.1.12. Now i want this value to be passed to my main page.
Please any one help to pass this value from default.aspx to my main page.
Thanks
Your default.aspx page will have an <object> tag where the Silverlight plugin is loaded. You can added a <param name="initParams value="clientID=192.168.1.12"> so it looks something like:-
<form id="form1" runat="server" style="height:100%">
<div id="silverlightControlHost">
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/Silverlight3App.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40818.0" />
<param name="autoUpgrade" value="true" />
<param name="initParams` value="clientID=192.168.1.12"`>
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
</form>
Except of course you wouldn't hardcode the IP address but you'd inject that with some VB.NET code (I don't do VB.NET).
The initParams parameter is a set of name=value pairs that are exposed in Silverlight as a IDictionary(Of String, String). You can get this dictionary from the Application Startup event arguments or from Application.Current.Host.InitParams.

I can't submit a form with Dojo DateTextBox

I'm working on a project with struts2 and dojo. Our dojo version is 1.4.x
I can't submit a form with DateTextBox control when my browser language is English.
However, when I change the local into other language like ZH_CN, it works.
I'm wondering why this would happen.
Here is my jsp code snippet:
<div id="projectForm" dojotype="dijit.form.Form">
<!-- end Date -->
<span class="manager_create_from_components">
<s:text name="manager.create.endDate"></s:text>
</span>
<input type="text" name="project.endDate" constraints="{datePattern:'yyyy-MM-dd'}" dojotype="dijit.form.DateTextBox"><br />
</div>
Thanks for you help.
HTTP Status 404 - No result defined for action
com.ternwit.tms.web.action.ManagerAction and result input.
This error is due to the fact you don't specified a result page in your struts.xml
<action name="actionName" class="package.yourClass" method="yourMethod">
<result name="success">successPage.jsp</result>
<result name="error">errorPage.jsp</result>
<result name="input">errorPage.jsp (or yourFormPage.jsp)</result>
</action>
Hope this helped
And about the dateTextBox, I have the same problem as you have. I think it's because of the value returned. Ex : "Wed Nov 16 2011 00:00:00 GMT+0100"