Jump to: navigation, search

Difference between revisions of "Scout/Tutorial/3.8/Jython Integration"

< Scout‎ | Tutorial‎ | 3.8
(Building the Jythonlib.jar)
m (add ScoutPage)
 
(16 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
{{ScoutPage|cat=Tutorial 3.8}}
 +
 
== Introduction ==
 
== Introduction ==
  
Line 11: Line 13:
 
== Building the Jythonlib.jar ==
 
== Building the Jythonlib.jar ==
  
For this example we need the jython.jar library extended with the set of the Python standard modules typically provided in the ''Lib'' folder. After downloading jython from the [http://www.jython.org/downloads.html official download page] and installing it to some arbitrary directory you should find therer the following to items:
+
For this example we need the jython.jar library extended with the set of the Python standard modules typically provided in the ''Lib'' folder. After downloading jython from the [http://www.jython.org/downloads.html official download page] and installing it to some arbitrary directory you should find the following two items:
 
* jython.jar
 
* jython.jar
 
* Lib
 
* Lib
  
Now, we are ready to build our '''jythonlib.jar''' according to the [http://wiki.python.org/jython/LearningJython#add-jython-install-stuff-to-our-jar description provided] in the jython Wiki (in case the description moves to some other location it is repeated below):
+
Now we are ready to build our '''jythonlib.jar''' according to the [http://wiki.python.org/jython/LearningJython#add-jython-install-stuff-to-our-jar description provided] in the jython Wiki (in case the description moves to some other location it is repeated below):
  
 
To build our jar, we first make a copy of jython.jar, then add the
 
To build our jar, we first make a copy of jython.jar, then add the
contents of the ''Lib/'' directory (eg Lib/re.py) to it::
+
contents of the ''Lib/'' directory (eg Lib/re.py) to it:
  
 
     $ cd $JYTHON_HOME
 
     $ cd $JYTHON_HOME
Line 25: Line 27:
  
 
== Create New Scout Project and add the Library bundle ==
 
== Create New Scout Project and add the Library bundle ==
bla
+
Create a new Scout project as described in the [[{{BASEPAGENAME}}/HelloWorld|Hello World tutorial]] with the following differences:
 +
* Use ''org.eclipse.scout.jythontest'' as the project name.
 +
* Don't (yet) add any form fields
 +
 
 +
Once the application model is shown in the Scout Explorer we can add the library bundle. To keep things as simple as possible in this example, we directly use the jython library in the client application. For this, select folder ''libraries'' below the orange client node in the Scout explorer. Then right-click on context menu ''New Library Bundle ...''
 +
 
 +
[[Image:Sdk_new_library_1.png‎ ]]
 +
 
 +
In the first dialog of the ''New Library Bundle'' wizard click on the ''Add'' button to select the jythonlib.jar file that we created above (in this step, one or several libraries may be assinged to a new bundle). That's it, we can now click on ''Finish''. The curious reader can click on ''Next'' to see the second dialog of the wizard. For this tutorial all the filled-in default values make sense and don't need to be changed, so please click ''Finish'' now.
 +
 
 +
[[Image:Sdk_new_library_2.png‎ ]] [[Image:Sdk_new_library_3.png‎ ]]
 +
 
 +
Behind the scenes the Scout SDK wizard has created the plugin ''org.eclipse.scout.jython.jythonlib'' and added it as a required dependency to the client plugin ''org.eclipse.scout.jython.client'' with the result that we can now access all elements in our jythonlib.jar as if it were part of the client bundle.
  
 
== Add and Configure the Form Fields on the Desktop Form ==
 
== Add and Configure the Form Fields on the Desktop Form ==
bla
+
 
 +
In the Scout Explorer expand the ''DesktopForm'' in the folder ''Forms'' below the orange client node and select the ''MainBox'' element.
 +
* In the Scout Object Properties of the ''MainBox'' Set the ''Grid Column Count'' attribute to 1.
 +
* On the ''MainBox'' in the Scout Explorer use context menu ''New Form Field ...''
 +
* Type ''Group box'' in the dialog's seach field and click ''Next''
 +
* In the field ''Class name'' enter '''DesktopBox''' and click on ''Finish''
 +
 
 +
Inside the ''DesktopBox''
 +
* Add a String field "Line" (double click on ''New Translated Text ...'' in dropdown field to add the proper text translations)
 +
* Add a String field "Python"
 +
* Add a Sequence Box with ''Class name'' "VariableBox"
 +
* Add a String field "Result"
 +
 
 +
Inside the ''VariableBox'' add the following UI components
 +
* Add a String field "Input"
 +
* Add a String field "Output"
 +
* Add a Button "Run"
 +
 
 +
Now configure the "Python" field
 +
* In the Scout Object Properties set ''Grid H'' to 5
 +
* Select attribute ''Multiline Text''
 +
* Open section ''Advanced Properties''
 +
* For the ''Tooltip Text'' insert the following text (using PythonExample as key)
 +
<source lang="python">
 +
tok = input.split()
 +
out = []
 +
i = 0
 +
 
 +
for t in tok:
 +
  i+=1
 +
  out.append("[%i] %s" % (i,t))
 +
 
 +
output = '\n'.join(out)
 +
</source>
 +
* Set the attribute ''Background Color'' to E1EAFF (or use the color picker)
 +
* For attribute ''Font'' select Courier New
 +
 
 +
Finally, for the "Result" field
 +
* Set the "Grid H" property to 3
 +
* Select attribute ''Multiline Text''
  
 
== Add Logic for Jython Interpreter and Interaction with Scout Form ==
 
== Add Logic for Jython Interpreter and Interaction with Scout Form ==
Line 34: Line 87:
 
# In the Scout Object Properties click on the green plus-icon next to the link ''Exec Click Action'' to add the corresponding method
 
# In the Scout Object Properties click on the green plus-icon next to the link ''Exec Click Action'' to add the corresponding method
 
# Replace the proposed implementation with the code provided below
 
# Replace the proposed implementation with the code provided below
 +
<source lang="java">
 +
@Override
 +
protected void execClickAction() throws ProcessingException {
 +
  getResultField().clearErrorStatus();
 +
  try {
 +
    // make sure Lib is visible to access python modules
 +
    PySystemState sys = Py.getSystemState();
 +
    PyString pyLibPath = new PyString("__pyclasspath__/Lib");
  
  @Override
+
     if (!sys.path.contains(pyLibPath)) {
  protected void execClickAction() throws ProcessingException {
+
      sys.path.append(pyLibPath);
     getResultField().clearErrorStatus();
+
    try {
+
      // make sure Lib is visible to access python modules
+
      PySystemState sys = Py.getSystemState();
+
      PyString pyLibPath = new PyString("__pyclasspath__/Lib");
+
     
+
      if (!sys.path.contains(pyLibPath)) {
+
        sys.path.append(pyLibPath);
+
      }
+
     
+
      // get interpreter, read input variable from input field
+
      PythonInterpreter pi = new PythonInterpreter();
+
      pi.set(getInputField().getValue(), new PyString(getLineField().getValue()));
+
     
+
      // run script, transfer output to result field
+
      pi.exec(getPythonField().getValue());
+
      getResultField().setValue(pi.get(getOutputField().getValue()).asString());
+
    }
+
    catch (Exception e) {
+
      getResultField().setValue(null);
+
      getResultField().setErrorStatus(e.toString());
+
 
     }
 
     }
 +
 +
    // get interpreter, read input variable from input field
 +
    PythonInterpreter pi = new PythonInterpreter();
 +
    pi.set(getInputField().getValue(), new PyString(getLineField().getValue()));
 +
   
 +
    // run script, transfer output to result field
 +
    pi.exec(getPythonField().getValue());
 +
    getResultField().setValue(pi.get(getOutputField().getValue()).asString());
 +
  }
 +
  catch (Exception e) {
 +
    getResultField().setValue(null);
 +
    getResultField().setErrorStatus(e.toString());
 
   }
 
   }
 +
}
 +
</source>
  
 
Remarks:  
 
Remarks:  
* Updating the ''sys.path'' should conceptually go to a place where it's calles once per client startup.  
+
* Updating the ''sys.path'' should conceptually go to a place such that it is called once per client startup.  
 
* There might be more elegant ways to ensure Jython is able to access the Python modules provided in the ''Lib'' subfolder of the ''jythonlib.jar''.
 
* There might be more elegant ways to ensure Jython is able to access the Python modules provided in the ''Lib'' subfolder of the ''jythonlib.jar''.
  
Line 69: Line 123:
 
# Select top level element ''org.eclipse.scout.jythontest'' in the Scout Explorer
 
# Select top level element ''org.eclipse.scout.jythontest'' in the Scout Explorer
 
# Start the server by clicking on the corresponding icon in the server box of the section ''Product Launchers''
 
# Start the server by clicking on the corresponding icon in the server box of the section ''Product Launchers''
# Start a client by clicking on acorresponding icon in a client box (Swing, SWT, or RAP)
+
# Start a client by clicking on corresponding icon in a client box (Swing, SWT, or RAP)
 
# The client starts and the desktop form is shown
 
# The client starts and the desktop form is shown
  
Line 75: Line 129:
 
# Enter some text into the ''Line'' field. For example '''hello world'''
 
# Enter some text into the ''Line'' field. For example '''hello world'''
 
# Enter a python script into the ''Python'' field. Example script:
 
# Enter a python script into the ''Python'' field. Example script:
  import re
+
<source lang="python">
 
+
import re
  tok = input_line.split()
+
 
  out = []
+
tok = input_line.split()
  i = 0
+
out = []
 
+
i = 0
  for t in tok:
+
 
    i+=1
+
for t in tok:
    if re.search(t, "hello", re.I):
+
  i+=1
      out.append("[%i] %s -- HELLO FOUND" % (i,t))
+
  if re.search(t, "hello", re.I):
    else:
+
    out.append("[%i] %s -- HELLO FOUND" % (i,t))
      out.append("[%i] %s" % (i,t))
+
  else:
 
+
    out.append("[%i] %s" % (i,t))
  output_text = '\n'.join(out)
+
 
 +
output_text = '\n'.join(out)
 +
</source>
  
 
Add the Binding Names for Input and Output
 
Add the Binding Names for Input and Output

Latest revision as of 01:58, 17 October 2012


Scout
Wiki Home
Website
DownloadGit
Community
ForumsBlogTwitter
Bugzilla
Bugzilla


Introduction

With Release 3.8 the Scout SDK offers support to integrate external JAR files into a Scout application with a few clicks. In this tutorial we use this capability to demonstrate how Jython may be integrated in your Scout application.

According to the Wiki "Jython is a Java implementation of Python" and Python itself claims "You can learn to use Python and see almost immediate gains in productivity and lower maintenance costs." In any case, we need an example library here and combining Java with a powerful scripting language can help to solve a significant variety of problems.

The result at the end of this tutorial will look similar to the screenshot below:

Jython integration.png

Building the Jythonlib.jar

For this example we need the jython.jar library extended with the set of the Python standard modules typically provided in the Lib folder. After downloading jython from the official download page and installing it to some arbitrary directory you should find the following two items:

  • jython.jar
  • Lib

Now we are ready to build our jythonlib.jar according to the description provided in the jython Wiki (in case the description moves to some other location it is repeated below):

To build our jar, we first make a copy of jython.jar, then add the contents of the Lib/ directory (eg Lib/re.py) to it:

   $ cd $JYTHON_HOME
   $ cp jython.jar jythonlib.jar
   $ zip -r jythonlib.jar Lib

Create New Scout Project and add the Library bundle

Create a new Scout project as described in the Hello World tutorial with the following differences:

  • Use org.eclipse.scout.jythontest as the project name.
  • Don't (yet) add any form fields

Once the application model is shown in the Scout Explorer we can add the library bundle. To keep things as simple as possible in this example, we directly use the jython library in the client application. For this, select folder libraries below the orange client node in the Scout explorer. Then right-click on context menu New Library Bundle ...

Sdk new library 1.png

In the first dialog of the New Library Bundle wizard click on the Add button to select the jythonlib.jar file that we created above (in this step, one or several libraries may be assinged to a new bundle). That's it, we can now click on Finish. The curious reader can click on Next to see the second dialog of the wizard. For this tutorial all the filled-in default values make sense and don't need to be changed, so please click Finish now.

Sdk new library 2.png Sdk new library 3.png

Behind the scenes the Scout SDK wizard has created the plugin org.eclipse.scout.jython.jythonlib and added it as a required dependency to the client plugin org.eclipse.scout.jython.client with the result that we can now access all elements in our jythonlib.jar as if it were part of the client bundle.

Add and Configure the Form Fields on the Desktop Form

In the Scout Explorer expand the DesktopForm in the folder Forms below the orange client node and select the MainBox element.

  • In the Scout Object Properties of the MainBox Set the Grid Column Count attribute to 1.
  • On the MainBox in the Scout Explorer use context menu New Form Field ...
  • Type Group box in the dialog's seach field and click Next
  • In the field Class name enter DesktopBox and click on Finish

Inside the DesktopBox

  • Add a String field "Line" (double click on New Translated Text ... in dropdown field to add the proper text translations)
  • Add a String field "Python"
  • Add a Sequence Box with Class name "VariableBox"
  • Add a String field "Result"

Inside the VariableBox add the following UI components

  • Add a String field "Input"
  • Add a String field "Output"
  • Add a Button "Run"

Now configure the "Python" field

  • In the Scout Object Properties set Grid H to 5
  • Select attribute Multiline Text
  • Open section Advanced Properties
  • For the Tooltip Text insert the following text (using PythonExample as key)
tok = input.split()
out = []
i = 0
 
for t in tok:
  i+=1
  out.append("[%i] %s" % (i,t))
 
output = '\n'.join(out)
  • Set the attribute Background Color to E1EAFF (or use the color picker)
  • For attribute Font select Courier New

Finally, for the "Result" field

  • Set the "Grid H" property to 3
  • Select attribute Multiline Text

Add Logic for Jython Interpreter and Interaction with Scout Form

  1. In the Scout Explorer select the RunButton element of the DesktopForm
  2. In the Scout Object Properties click on the green plus-icon next to the link Exec Click Action to add the corresponding method
  3. Replace the proposed implementation with the code provided below
@Override
protected void execClickAction() throws ProcessingException {
  getResultField().clearErrorStatus();
  try {
    // make sure Lib is visible to access python modules
    PySystemState sys = Py.getSystemState();
    PyString pyLibPath = new PyString("__pyclasspath__/Lib");
 
    if (!sys.path.contains(pyLibPath)) {
      sys.path.append(pyLibPath);
    }
 
    // get interpreter, read input variable from input field
    PythonInterpreter pi = new PythonInterpreter();
    pi.set(getInputField().getValue(), new PyString(getLineField().getValue()));
 
    // run script, transfer output to result field
    pi.exec(getPythonField().getValue());
    getResultField().setValue(pi.get(getOutputField().getValue()).asString());
  }
  catch (Exception e) {
    getResultField().setValue(null);
    getResultField().setErrorStatus(e.toString());
  }
}

Remarks:

  • Updating the sys.path should conceptually go to a place such that it is called once per client startup.
  • There might be more elegant ways to ensure Jython is able to access the Python modules provided in the Lib subfolder of the jythonlib.jar.

Play around

In the Scout SDK do the following

  1. Select top level element org.eclipse.scout.jythontest in the Scout Explorer
  2. Start the server by clicking on the corresponding icon in the server box of the section Product Launchers
  3. Start a client by clicking on corresponding icon in a client box (Swing, SWT, or RAP)
  4. The client starts and the desktop form is shown

In the Application do the following

  1. Enter some text into the Line field. For example hello world
  2. Enter a python script into the Python field. Example script:
import re
 
tok = input_line.split()
out = []
i = 0
 
for t in tok:
  i+=1
  if re.search(t, "hello", re.I):
    out.append("[%i] %s -- HELLO FOUND" % (i,t))
  else:
    out.append("[%i] %s" % (i,t))
 
output_text = '\n'.join(out)

Add the Binding Names for Input and Output

  1. In field Input specify the Python variable representing the text in the Line field. For the example above, use input_line
  2. In field Output specify the Python variable holding the output of the Python script. For the example above, use output_text
  3. Click on Run. The content of the output variable defined above is transferred to the form field Result