0

What I want to do:

  • I want to call a javaScript function from a Bean-function
  • Then I want to pause my Bean-function
  • Then the JavaScript function do it's own thing and returns stuff back to the bean
  • Then the Bean-function wakes up and handle the result

Details:

  • I am using JSF 2.2, and ICEfaces 4.2.0.
  • I am using JavaScriptRunner.runScript() to call a javascript function. (This works well)
  • Calling bean function from JavaScript works well
  • According to the docs about JavaScriptRunner.runScript() the function should "Send immediately Javascript code to the client for evaluation and execution"

Problem:

  • The problem is that the javaScript function won't be called before the bean code has ended.

Is it possible to start the javaScript function by interrupting the bean-function?


EDIT:

Added an example Bean of how I how thought it should work, if it helps:

public class MyBean {

  public String callJavaScriptFunctionAndWaitAndHandleResult() {

    // Call a javascript function from the bean
    callJavaScriptFunction();

    // Waits untill the javascript has returned some stuff
    pause(); // <-- IS IT POSSIBLE TO WAIT HERE AND RUN A JAVASCIPT FUNCTION?

    // Handle the result you got from the javascript function
    handleResultFromJavaScript();
  }
}
OuuGiii
  • 1,053
  • 1
  • 11
  • 31
  • 1
    You could try using http://showcase.omnifaces.org/push/socket – Jasper de Vries Feb 12 '19 at 11:12
  • 1
    Either you effectively just have a new request (not 'stopping/pausing' the bean) or you need something like push https://stackoverflow.com/questions/3787514/how-can-server-push-asynchronous-changes-to-a-html-page-created-by-jsf – Kukeltje Feb 12 '19 at 12:59
  • The logic is strange. You can just remove `pause()` altogether and move `handleJavaScriptResult()` into the place of `continueAtLastPlace()` and remove the `continueAtLastPlace()` itself. Or is there any specific reason for this logic? – BalusC Feb 12 '19 at 14:33
  • Yes, there is a specific reason, and it is because I would like to be able to call the javascript function anywhere in my application and handle the result I get directly after the result has been returned. I have updated the bean so that the first function will return the result. @BalusC – OuuGiii Feb 12 '19 at 15:07
  • Not java-se related. You cannot reproduce in a plain jdk without additional libraries and one class with just a main method – Kukeltje Feb 12 '19 at 17:51
  • @Kukeltje, sorry, I do not understand your comment, could you please elaborate what you mean and why it is relevant to my question? – OuuGiii Feb 13 '19 at 08:40
  • Please elaborate on which comment. I made 2 – Kukeltje Feb 13 '19 at 10:09
  • The second one @Kukeltje – OuuGiii Feb 13 '19 at 10:31
  • If you can create a problem in a small piece of code like mentioned in the 'HelloWorld' in https://stackoverflow.com/tags/java/info then you should use the java tag. – Kukeltje Feb 13 '19 at 11:24
  • Someone with a higher reputation wanted the java-tag to go away in the beginning, so I took it, but I have now put it back. Aren't you also able to add a tags? @Kukeltje – OuuGiii Feb 13 '19 at 11:59
  • 2
    You should restrict tags to the ones which are answerable by the experts of the said tag. [java] experts and [javascript] experts generally know absolutely nothing about [jsf]. So [java] and [javascript] tags attract incorrect audience. Generally, you can use [java] tag if your problem is *fully demonstrable* using a plain vanilla Java class with a `main()` method. Your current problem clearly isn't. – BalusC Feb 13 '19 at 12:13
  • 1
    I was the one that removed it... twice...with reasons specified and maybe explained in more detail (taking more time) by @BalusC – Kukeltje Feb 13 '19 at 12:20
  • Thanks, now I understood what you meant @Kukeltje – OuuGiii Feb 13 '19 at 12:25
  • Is it possible by using ICEfaces ICEpush to start a javascript function? @Kukeltje – OuuGiii Feb 13 '19 at 15:31
  • No idea, don't use icefaces, but if it can push a string, I would expect it would be able to execute it via `eval` – Kukeltje Feb 13 '19 at 15:43
  • The ICEpush does NOT interrupt the bean function, but it renders the part you want to render AFTER it has gone through the whole bean code. – OuuGiii Feb 18 '19 at 10:49
  • 1
    Yes, and? Nobody said it could interrupt/pause a bean and let the JSF flow work, **NOTHING CAN DO THAT**. It was a suggestion to rethink your solution (and maybe you even have an http://xyproblem.info). What you effectively need is a call then ends when it returns javascript, and from that javascript call a remote command that calls a new bean... https://stackoverflow.com/questions/16588327/how-to-invoke-a-jsf-managed-bean-on-a-html-dom-event-using-native-javascript – Kukeltje Feb 18 '19 at 13:13
  • I just wanted to inform others if they landed on this question. And thank you for answering the question "**NOTHING CAN DO THAT**" is the only answer so far which answer my question. And thanks for bringing an alternate solution, others will probably find it useful. @Kukeltje – OuuGiii Feb 19 '19 at 08:03
  • If you want, and if you are sure about it, you can answer the question and mention the alternate solution so if someone find this question it will be easier to see the answer. @Kukeltje – OuuGiii Feb 19 '19 at 08:06

1 Answers1

2

Disclaimer: Code in the answer will contain untested code in PrimeFaces flavour and 'pseudo code'. Since I do not use/run IceFaces nor do I have the intention to, I cannot (will not) test the code and will only provide the PrimeFaces counterparts as an (untested) example

Answer

You seem to be stuck trying to get a technical solution to work that cannot work. JSF cannot 'pause' things and will only return data at the end of the bean method that is called. You are most likely mislead by the statement in the IcesFaces documentation

"Send immediately Javascript code to the client for evaluation and execution"

This cannot work due to the way JSF works and it is sort of not really good English. The developers should have stated something like

"Send Javascript code to the client at the end of the method call for immediate evaluation and execution"

The immediate means that it is not some <script> .... </script> that gets added to the page and that can be executed again and again by e.g. calling a function that is defined in the script. It does not mean you cannot call existing javasript functions (ones that are already in your DOM) from the returned script (effectively that is what we will be using)

So how to solve your problem. Start by breaking the method down in two, lets call them step1 and step2

void step1() {

    // Do things

    // return javascript

}

void step2() {

    // Do other things using values that will be posted from the client by javascript

}

How to return javascript/call javascript from a bean is an existing Q/A here in Stackoverflow. For the IcesFaces counterpart I refer to their documentation. A PrimeFaces example is

PrimeFaces.current().executeScript("alert('This onload script is added from backing bean.'); clientSideFunction();");

But at the end of the javascript you want to call a server side method in a bean from javascript. The opposite of what you need in step one.

A PrimeFaces example being

<p:remoteCommand name="clientSideFunction" action="#{bean.step2}" />

And in since in calling step2() you want to pass parameters to the bean, you need to implement this as well.

clientSideFunction([{name:'x', value:10}, {name:'y', value:20}]);

You can use javascript variables in there (e.g. a complete json string in a variable) and need to process these variables (especially see the 'update' at the end)

Kukeltje
  • 12,223
  • 4
  • 24
  • 47