12 Replies Latest reply on Jun 5, 2007 9:30 AM by Jean-Louis Rastapoc

    Signal a task on a html form submit

    Jean-Louis Rastapoc Newbie

      Hi,

      I want to end a task on a file upload. So I made a form in the xhtml form file with a file input. On the server side I deploy a servlet to get the file... and signal the token.

      I tried to pass the tokenId from the form to the servlet by doing that in the form:

      <input name="tokenId" type="hidden" value="#{token.getId}"/>


      and that in the servlet:
      tokenId=tokenIdItem.getString();


      ... but I get an empty answer.


      Do you see something wrong here? Maybe an expression mistake?


      I search for other ways to get my task or token or processInstance in the servlet but I failed too : I got potentially a lot of the same processDefinition at the same task with either different or same actors/variables so I didn't find any way to get the one I want.

      Do you know another way to signal my task on the form submit button that I could have missed?


      PS: sorry if my english is too bad :/

        • 1. Re: Signal a task on a html form submit
          Jean-Louis Rastapoc Newbie

          Just some precisions :
          - I spent lot of time trying everything (taskInstance, processIntance and not only token) in my expressions and I never get any answer. I don't know why since it works well with any simple variable (with "#{var['myvar']}").
          - This input code is in a modified form file created by the GPD. I need to have 2 solutions here : the first is a normal transition link and the second the file upload. They lead to the same unique transition to the next node.


          I searched the documentation and I understand that the way I do it should work.. is it a bug? (I'm not know EL enough to figure myself)
          I searched in all the test cases and I didn't find any example of that... did I miss one?

          I lost nearly a day on that so if you have any little idea... even if it may seem stupid... I'll take it and test it.

          • 2. Re: Signal a task on a html form submit
            Ronald van Kuijk Master

            - you describe you deployed 'a servlet' how can we know what goes wrong if you do not show the code
            - you do not describe what versions of the gpd, core etc, - how do we know what is the original form (you made 'a' form in 'the' xhtml form file)
            - why do you come to the conclusion that after reading the docs you understand that the way you do it is correct?

            etc...etc...etc...

            if you are not more explicit, people cannot help you

            • 3. Re: Signal a task on a html form submit
              Jean-Louis Rastapoc Newbie

              Ok I post you some code and informations... It will not say more that I already said... but ok let's go.

              Here is my task :

              <task-node name="Creer bilan">
               <task name="bilanCP">
               <assignment actor-id="#{CP}" />
               </task>
               <transition to="Evaluation DP" name="OK"></transition>
               </task-node>
              


              Here is my association in the forms.xml :
              <form task="bilanCP" form="bilanCP.xhtml"/>


              Here is my bilanCP.xhtml (displaying well) :
              <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
              
              <html xmlns="http://www.w3.org/1999/xhtml"
               xmlns:ui="http://java.sun.com/jsf/facelets"
               xmlns:c="http://java.sun.com/jstl/core"
               xmlns:h="http://java.sun.com/jsf/html"
               xmlns:f="http://java.sun.com/jsf/core"
               xmlns:tf="http://jbpm.org/jsf/tf"
               xmlns:jbpm="http://jbpm.org/jsf">
              
               <ui:component>
               <form enctype="multipart/form-data" method="POST" action="uploadSuivi">
               <jbpm:dataform>
               <f:facet name="header">
               Envoyer un fichier local
               </f:facet>
               <jbpm:datacell>
               <f:facet name="header">
               Selectionnez le fichier a envoyer :
               </f:facet>
               <input class="file" type="file" name="suiviXLS"/>
               <input name="nomProjet" type="hidden" value="#{var['nomProjet']}"/>
               <input name="tokenId" type="hidden" value="#{token.getId}"/>
               </jbpm:datacell>
              
               <jbpm:datacell>
               <f:facet name="header">
               <h:outputText value="Actions"/>
               </f:facet>
               <button class="button" type="submit">Envoyer</button>
               </jbpm:datacell>
              
               </jbpm:dataform>
               </form>
              
               <br />
              
               <jbpm:dataform>
               <f:facet name="header">
               <h:outputText value="Fichier distant modifie"/>
               </f:facet>
              
               <jbpm:datacell>
               <f:facet name="header">
               <h:outputText value="Actions"/>
               </f:facet>
               <!-- TASKFORM BUTTONS -->
               <tf:transitionButton transition="OK" value="Faire suivre le fichier au DP"/>
               </jbpm:datacell>
               </jbpm:dataform>
              
              </ui:component>
              
              </html>
              


              and here is my servlet :

              import java.io.File;
              import java.io.IOException;
              import java.io.PrintWriter;
              import java.util.Iterator;
              import java.util.List;
              
              import javax.servlet.http.HttpServlet;
              import javax.servlet.http.HttpServletRequest;
              import javax.servlet.http.HttpServletResponse;
              
              import org.apache.commons.fileupload.FileItem;
              import org.apache.commons.fileupload.FileItemFactory;
              import org.apache.commons.fileupload.servlet.ServletFileUpload;
              import org.apache.commons.fileupload.disk.DiskFileItemFactory;
              
              public class UploadSuivi extends HttpServlet {
              
               private static final long serialVersionUID = -7214369336993351418L;
              
               private FileItem fichier;
               private String nomProjet;
               private String tokenId;
              
               public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
              
               if (!ServletFileUpload.isMultipartContent(request)) {
               throw new RuntimeException("Not a multipart request");
               }
              
               try {
               // Create a factory for disk-based file items
               FileItemFactory factory = new DiskFileItemFactory();
              
               // Create a new file upload handler
               ServletFileUpload upload = new ServletFileUpload(factory);
              
               // Parse the request
               List list = upload.parseRequest(request);
              
               // Process the uploaded items
              
               for (int i=0; i<list.size(); i++) {
               FileItem item = (FileItem) list.get(i);
              
               if (item.getFieldName().compareTo("suiviXLS") == 0) {
               fichier = item;
               }
              
               if (item.getFieldName().compareTo("nomProjet") == 0) {
               nomProjet=item.getString();
               }
              
               if (item.getFieldName().compareTo("tokenId") == 0) {
               tokenId=item.getString();
               }
               }
              
               // save the file
               File uploadedFile = new File("C:/"+nomProjet+".xls");
               fichier.write(uploadedFile);
              
               // signal the task
              
               // redirtection vers la page des taches
               response.sendRedirect(response.encodeRedirectURL("search/tasks.jsf"));
               } catch (Exception e) {
               throw new RuntimeException("Exception quelque part...", e);
               }
               }
              }
              


              The code is ugly, I know, it's because it's not finished at all...
              At the end of the execution I got my file, my project name variable in nomProjet and an empty string in tokenId (so it goes in the if statement and does the getString on the third item).


              I understand that my token.getId should work from this part of documentation (section 18.3, I can copy paste it: it's really short) and the link given to EL:
              For some of the delegations, there is support for a JSP/JSF EL like expression language. In actions, assignments and decision conditions, you can write an expression like e.g. expression="#{myVar.handler[assignments].assign}"
              
              The basics of this expression language can be found in the J2EE tutorial.
              
              The jPDL expression language is similar to the JSF expression language. Meaning that jPDL EL is based on JSP EL, but it uses #{...} notation and that it includes support for method binding.
              
              Depending on the context, the process variables or task instance variables can be used as starting variables along with the following implicit objects:
              
               * taskInstance (org.jbpm.taskmgmt.exe.TaskInstance)
               * processInstance (org.jbpm.graph.exe.ProcessInstance)
               * processDefinition (org.jbpm.graph.def.ProcessDefinition)
               * token (org.jbpm.graph.exe.Token)
               * taskMgmtInstance (org.jbpm.taskmgmt.exe.TaskMgmtInstance)
               * contextInstance (org.jbpm.context.exe.ContextInstance)


              I'm not an expert in all the JSF and EL and even if I didn't find anything to help me looking these parts.

              I'm using the jBPM 3.2 suite (sorry I forgot to mention that) and GPD 3.0.13 to deploy and have the process definition and forms skeleton (I write a lot by myself after... I'm waiting the new GPD (seems great) to leave the alpha and beta states before using it :) ).

              If you want to know everything :
              - I customize the example web application to fit my needs by removing some administration parts, adding servlets and others things I need,
              - I begin to use the new admin console from CVS (I think I will somehow merge the two at the end),
              - my shoes size is 10 and... ok I stop here :)

              Hope it helps...

              • 4. Re: Signal a task on a html form submit
                Jean-Louis Rastapoc Newbie

                I forget to say it again : I know I may I misunderstood the documentation. I d'ont say it's a bug... but in case I read well it can be... I just don't know and I'm curious about it.

                What I want now is another solution to get my process instance, token or whatever so I can signal my task in my servlet. I'm sure there's an easy one somewhere but I just don't imagine it yet...

                • 5. Re: Signal a task on a html form submit
                  Ronald van Kuijk Master

                   

                  Ok I post you some code and informations... It will not say more that I already said... but ok let's go.


                  Well,

                  tokenId=item.getString();


                  differs from
                  tokenId=tokenIdItem.getString();


                  and the accompanying form tells more about the 'correct' implementation than single lines of code, so please let us be the judge of whether it tells more/enough ok ;-)

                  What does the generated form look like in the browser? Does the token field have a value?

                  Maybe try something like "#{task.token.id)"

                  Whow... now I see where you go wrong......

                  you do a token.getId instead of token.id......





                  • 6. Re: Signal a task on a html form submit
                    Jean-Louis Rastapoc Newbie

                    I doesn't work better with id at the end or/and with task in the begining.
                    My field remains empty (and empty in the browser too if not hidden).
                    I tried idParameter instead of id only too (I see that in a jbpm:bind... just in case...) and it doesn't work better.

                    Right now I'm trying to add the processInstance ID to the context variables with an action. That way I'm sure I'll get it in my servlet. It doesn't work yet but it will... I hope it will :)
                    Too bad I have to add code and use a process variable for that though...

                    • 7. Re: Signal a task on a html form submit
                      Edward Staub Expert

                      Ronald,

                      I see a lot of instances on the forum of folks who have problems with EL and don't (apparently) have any way to dig into what they've done wrong beyond inspection of their code. It's much more common with transition condition expressions.

                      Do you know if there's any way to turn on EL tracing so that, e.g., in this case, he'd see somewhere in a log a "No Such Field 'getId'" error message?

                      -Ed Staub

                      • 8. Re: Signal a task on a html form submit
                        Ronald van Kuijk Master

                        Ed,

                        This is generic EL stuff.... ig you have e.g. a class Token with getter/setter like getId/setId, in EL you have to use token.id to have access to it.

                        If it is the jboss imp, it uses log4j, so turning on debug at the rootlevel (and reducing it to the correct classes/packages if you see some interesting stuff) is what I normally do.

                        In the webconsole I see something like:

                         <jbpm:dataarea>
                         <h:inputHidden value="#{returnViewId}"/>
                         <h:inputHidden value="#{tokenId}"/>
                         ...
                         </jbpm:dataarea>
                        




                        • 9. Re: Signal a task on a html form submit
                          Edward Staub Expert

                          Ronald,

                          This is generic EL stuff.... ig you have e.g. a class Token with getter/setter like getId/setId, in EL you have to use token.id to have access to it.

                          Yeah, I know... it's just that we all do bonehead things like this once in a while and need a hint about where we screwed up. The log can provide this - maybe. I haven't used it in this area, so I don't know what log output is emitted and whether it is useful. I was hoping you might - I guess not, though!

                          If it is the jboss imp, it uses log4j, so turning on debug at the rootlevel (and reducing it to the correct classes/packages if you see some interesting stuff) is what I normally do.

                          Yes... I'm getting a sense that a lot of folks don't have the experience base for this to be an reflexive thing to do. I'm starting to wonder if it makes sense to include a log4j.xml in the config, just to steer folks toward taking advantage of it.

                          I guess JBPM may migrate at some point to use Seam's EL implementation relatively soon, so researching into specifics about log capabilities in the current implementation may not be that useful in the long term.

                          -Ed Staub


                          • 10. Re: Signal a task on a html form submit
                            Ronald van Kuijk Master

                            Oh... regarding these logoutputs, I have some experience in combination with seam and there is explicit logging on getters/setters not found on debug level. Sometimes even at error (not sure when exactely)

                            There was a configfile at the debug level, but afaik, there has been a change in policy lately to at least leave the console output with not that high a level and have the fileappender contain more detailed output, so not only look at the console!!!!

                            And yes, if it was up to Gavin et al, jBPM would make the switch to their EL impl asap (not sure if that one runs on jdk 1.4 though

                            • 11. Re: Signal a task on a html form submit
                              Jean-Louis Rastapoc Newbie

                              I just solved my problem. I was trying to get my taskInstance to be signaled with code when I thought about another solution :

                              I don't put a dataform inside my form but the form inside my dataform. This way the default transition button can still work and I just have to put some javascript on it like that :

                              <jbpm:dataform>
                               <f:facet name="header">
                               Envoyer un fichier local
                               </f:facet>
                               <jbpm:datacell>
                               <f:facet name="header">
                               Selectionnez le fichier a envoyer :
                               </f:facet>
                               <form name="uploadFile" enctype="multipart/form-data" method="POST" action="uploadSuivi">
                               <input class="file" type="file" name="suiviXLS"/>
                               <input class="text" type="hidden" name="nomProjet" value="#{var['nomProjet']}"/>
                               </form>
                               </jbpm:datacell>
                              
                               <jbpm:datacell>
                               <f:facet name="header">
                               <h:outputText value="Actions"/>
                               </f:facet>
                               <tf:transitionButton transition="OK" value="Envoyer" onclick="document.forms['uploadFile'].submit();"/>
                               </jbpm:datacell>
                               </jbpm:dataform>


                              It works well, my task is validated, the next task is created, my servlet is called and my file saved... I'm happy but I'm feeling very stupid to think about that so late. I knew this should be easy :)

                              Btw I think a little more documentation must be written on EL (some examples would be great) and since jBPM JSF tags are still here in the new admin console and usable from jBPM and JSF users, I think they deserve a little Javadoc like the official JSF one : http://java.sun.com/javaee/javaserverfaces/1.2_MR1/docs/tlddocs/index.html.
                              That's absolutly not a urgent task... but it would help...

                              • 12. Re: Signal a task on a html form submit
                                Jean-Louis Rastapoc Newbie

                                Hi,

                                I just come to add precisions on my previous solution (it can eventualy help).

                                Finally there is a big problem with the previous solution : you can't control the result of the servlet and the task is always validated. It didn't matter for me so far... but now I need it.

                                So I came back to the old solution and I'm now validating my task and everything in the servlet with the taskInstance ID I get in EL like that :

                                #{taskInstanceBean.taskInstance.id}