[JBoss jBPM] - Re: Fork Join and Async Nodes
by tak2
Our team has been evaluating jBPM as the main flow control platform, and this is literally show stopper.
Some threads and doc suggested to set isolation level to READ_COMITTED, but I don't think it can solve the issue.
When parallel nodes enter into Join node, Join.execute must be executed serialized fashion to check all parallel node status to decide to exit the join.
The issue seems like that Hibernate is treating Token object in optimistic locking fashion even in Join.execute method. But what we need in the Join scenario is pessimistic locking, because join will be executed by multiple thread possibly in different JVM, so database level parent Token record level locking is required.
Is it possible to use pessimistic locking only in Join.execute()?
Here is waht I tried with limited Hibernate knowledge, but all didn't work.
In execute method in Join node, when it call session.lock(parentToken, LockMode.FORCE), hibernate seems like incrementing version (why for locking???), and same operation to the same object in another thread throw StaleObjectStateException.
This is basic feature we need for concurrent operation, and very easy to implement with SQL based programming with "select for update".
I tried to LockMode.UPGRADE too, but the result was same.
So, I tried to called "select for update" against parent Token record instead of using session.lock(), and this operation worked as I expected, but when committing transaction on JbpmContext.close(), later thread still throw StaleObjectStateException.
OK, then I load object after getting lock (after select for update) by session.load(parentToken.getId(), Token.class, LockMode.UPGRADE), but surprisingly the parentToken object returned still had old version, even DB record was committed and version was incremented.
Am I doing something wrong?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4136872#4136872
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4136872
18 years, 1 month
[JBoss jBPM] - Re: StaleObjectStateException in a Fork with states
by tak2
Was this issue for the join with multi-threads fixed?
I am facing same issue, too.
My application server is Oracle, IBM, and Fujitsu with Oracle 10g DB.
I have two parallel asynchronous nodes between fork and join, and these node are executed by different thread via MDB.
Here is what I understood from code so far.
In execute method in Join node, when it call session.lock(parentToken, LockMode.FORCE), hibernate seems like incrementing version (why for locking???), and same operation to the same object in another thread throw StaleObjectStateException.
This is basic feature we need for concurrent operation, and very easy to implement with SQL based programming with "select for update".
I tried to LockMode.UPGRADE, but it's same.
So, I tried to called "select for update" against parent Token record instead of using session.lock(), and this operation worked as I expected, but when committing transaction on JbpmContext.close(), later thread still throw StaleObjectStateException.
OK, then I load object after getting lock (after select for update) by session.load(parentToken.getId(), Token.class, LockMode.UPGRADE), but surprisingly the parentToken object returned still had old version, even DB record was committed and version was incremented.
Does someone solve this issue?
or am I doing something wrong?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4136870#4136870
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4136870
18 years, 1 month
[Security & JAAS/JBoss] - Re: combination of JAAS
by eivind@kadme.com
Hi!
I was asked by a response to my blog post (http://roneiv.wordpress.com/2008/02/19/perform-a-jaas-programmatic-login-...) to comment and maybe help on this issue.
I'm no expert on these matters, but I've managed to use the WebAuthentication BOTH from servlet context and from a handler to login a user to the application. And the user is properly set also in web container, so both externalContext.getRemoteUser() AND externalContext.getUserPrincipal().toString() return the logged on username.
Zilbi, it is my understanding that you have managed to log on to your application whith basic form-logon, using j_security_check etc. That's nice, because we then know that your login-config and ds works. Still, I will provide an example of the login-config I use, just in case it matters ;) This one uses a database with a user table, but the groups are static:
| <application-policy name = "myApplication">
| <authentication>
| <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required">
| <module-option name = "dsJndiName">java:/myDatasource-ds</module-option>
| <module-option name = "principalsQuery">Select password from user_table where user_name =? AND active = 'true'</module-option>
| <module-option name = "rolesQuery">Select 'user', 'Roles', 'RoleGroups' from user_table where user_name =?</module-option>
| <module-option name ="hashAlgorithm">md5</module-option>
| <module-option name="hashEncoding">hex</module-option>
| <module-option name="debug">false</module-option>
| </login-module>
| <login-module code="org.jboss.security.ClientLoginModule" flag="required" />
| </authentication>
| </application-policy>
|
The first thing to try is that the WebAuthentication class works as it should.
Create a LoginHandler or something similar, with a method login() and two helper-methods getRemoteUser and getUserPrincipal. Something like this:
| public class LoginHandler
| {
|
| public String login()
| {
| WebAuthentication webAuthentication = new WebAuthentication();
|
| String hardcodedUserName = "zilbi(a)jboss.com";
| String hardcodedPassword = "zilbi123";
|
| if (webAuthentication.login(hardcodedUserName, hardcodedPassword))
| {
| System.out.println("Logged in successfully");;
|
| log.debug("userPrincipal: " + getUserPrincipal());
| log.debug("remoteUser: " + getRemoteUser());
| }
| else
| {
| log.debug("Login failed");
| }
|
| return "";
| }
| public String getUserPrincipal()
| {
| FacesContext context = FacesContext.getCurrentInstance();
| ExternalContext externalContext = context.getExternalContext();
| return externalContext.getUserPrincipal() != null ? externalContext.getUserPrincipal().toString() : "null";
| }
|
| public String getRemoteUser()
| {
| FacesContext context = FacesContext.getCurrentInstance();
| ExternalContext externalContext = context.getExternalContext();
| String remoteUser = externalContext.getRemoteUser();
| return remoteUser;
| }
|
| }
|
We basically hardcode the username/password, and just test if we get login to work. You should of course change these values to something that matches your login domain. Then create a simple jsp, but don't put it inside your protected folder. I see from you web.xml that you protect everything under /protected/*. Create it one level up so that you can access it without being asked to log in.
In this jsp you will have a stupid commandButton, as well as two outputs that displays the remoteUser and userPrincipal:
| <f:view >
| <t:document>
| <t:documentHead>
| <f:loadBundle basename="MessageResources" var="messages" />
| </t:documentHead>
|
| <f:verbatim>
| <body>
| </f:verbatim>
| <h:form>
| <h:panelGrid>
| <h:commandButton value="Login" action="#{loginHandler.login}"></h:commandButton>
| <h:outputText value="User Principal: #{loginHandler.userPrincipal}"></h:outputText>
| <h:outputText value="Remote User: #{loginHandler.remoteUser}"></h:outputText>
| </h:panelGrid>
| </h:form>
| <f:verbatim>
| </body>
| </f:verbatim>
| </t:document>
| </f:view>
|
Now, launch your application by going to this page. You will see that userPrincipal shows "null" and remoteUser is empty. Press the Login button. When the page reloads it should display your username in both outputTexts. If you check your log or console it should say "Logged in successfully." The user is now properly set in the web container. Do you get this to work? Also, if you now try to change the url to go to one of your protected pages, you should not be redirected to any login.jsp, but the page should display properly - because you are already logged on.
Then, to do the logon from a servlet there's really not a big difference. I set up my web.xml to use a FORM-based logon, like this:
| <login-config>
| <auth-method>FORM</auth-method>
| <form-login-config>
| <form-login-page>/login.faces</form-login-page>
| <form-error-page>/loginFailed.faces</form-error-page>
| </form-login-config>
| </login-config>
|
I also register my LoginServlet in web.xml like this:
| <servlet>
| <servlet-name>LoginServlet</servlet-name>
| <servlet-class>com.test.servlet.LoginServlet</servlet-class>
| </servlet>
|
| <servlet-mapping>
| <servlet-name>LoginServlet</servlet-name>
| <url-pattern>/LoginServlet</url-pattern>
| </servlet-mapping>
|
My login.jsp is 99% the same as when using j_security_check, we just point the action to the LoginServlet instead:
| <form method="POST" name="loginform" action="${pageContext.request.contextPath}/LoginServlet">
| <table style="vertical-align: middle;">
| <tr>
| <td>Username:</td><td><input type="text" name="j_username"/></td>
| </tr>
| <tr>
| <td>Password:</td><td><input type="password" name="j_password"/></td>
| </tr>
| <tr>
| <td><input type="submit" value="Login" /></td>
| </tr>
| </table>
| </form>
|
|
My LoginServlet uses the parameters that was originally passed to the j_security_check. Also, if we successfully log on, we get the "Referer" from the request to redirect to the page that originally was the target for the user. I did not include the code that handles if the logon failed here:
| public class LoginServlet extends HttpServlet
| {
| @Override
| protected void doGet(HttpServletRequest req, HttpServletResponse resp)
| throws ServletException, IOException
| {
| // TODO Auto-generated method stub
| doPost(req, resp);
|
| }
|
| @Override
| protected void doPost(HttpServletRequest req, HttpServletResponse resp)
| throws ServletException, IOException
| {
| String user = req.getParameter("j_username");
| String pass = req.getParameter("j_password");
| WebAuthentication webAuthentication = new WebAuthentication();
| if( webAuthentication.login(user, pass))
| {
| String redirectUrl = "";
| String referer = req.getHeader("Referer");
| resp.sendRedirect(redirectUrl);
| return;
| }
| else
| {
| System.out.println("Login attempt failed " + user);
| ...
| Handle incorrect logon, go back to login page etc
| ...
| }
| }
| }
|
So, to test this, start your application by pointing directly to some page that is protected. Your login.jsp should be presented, and when you press Login the servlet uses the credentials you passed in the forms, authenticates and redirect you to the page. For debug reasons you could add the same outputTexts here on this page (remoteUser and userPrincipal), and they SHOULD show the user you logged in with now.
Hope that this might help you, but as I said, I'm no expert on this. And I don't know the effect of the two options you include in your login-config, if this could cause some bad behaviour or not:
anonymous wrote :
| <module-option name="restore-login-identity">true</module-option>
| <module-option name="multi-threaded">true</module-option>
A good tip is to start with a minimal configuration till you get it working, and then slowly building it up to go where you want. :)
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4136856#4136856
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4136856
18 years, 1 month