Tag Archives: java

python interop: using jython and ironruby

in a project with java and .net komponents we needed to share some validation-code. this code should be executable on both platforms and act against pocos (plain old clr objects) and pojos (plain old java objects). we tested python as a language that can be executed on both sides using jython for java and ironpython for c#. i want to show you how simple an integration of python is here.

for c# and ironpython:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
 
namespace IronPythonValidationTest {
  internal class Program {
    private static void Main(string[] args) {
      string code = @"
if this.Von > this.Bis:
    result = 'von soll kleiner sein als bis'
elif this.Child.Name != '':
    result = 'name soll gefüllt sein'";
 
      ScriptEngine engine = Python.CreateEngine();
      ScriptScope scope = engine.CreateScope();
      scope.SetVariable("this", new TestType {Von = DateTime.Now.AddDays(1), Bis = DateTime.Now, Child = new TestTypeNested()});
      ScriptSource source = engine.CreateScriptSourceFromString(code, SourceCodeKind.SingleStatement);
      source.Execute(scope);
      string validationResult = scope.GetVariable("result");
      Console.WriteLine(validationResult);
      Console.ReadKey();
    }
  }
 
  public class TestType {
    public string Name { get; set; }
    public DateTime Von { get; set; }
    public DateTime Bis { get; set; }
    public TestTypeNested Child { get; set; }
  }
 
  public class TestTypeNested {
    public string NochName { get; set; }
  }
}

and almost the same for java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import org.python.util.PythonInterpreter;
import org.python.core.*;
 
public class JythonValidationTest {
 
	public static void main(String[] args) {
		PythonInterpreter python = new PythonInterpreter();
		String code = "if this.Von > this.Bis:\n    result = \"von soll kleiner sein als bis\"\nelif this.Child.Name != \"\":\n    result = \"name soll gefüllt sein\"";
		PyCode pc = python.compile(code);
		TestType l = new TestType();
		l.setVon(2);
        l.setBis(1);
		python.set("this", l);
	}	
}
 
// this has to be a public class, so one could not put it in one classfile
public class TestType {
    public int von;
    public String name;
    public int bis;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getVon() {
        return von;
    }
 
    public void setVon(int von) {
        this.von = von;
    }
 
    public int getBis() {
        return bis;
    }
 
    public void setBis(int bis) {
        this.bis = bis;
    }
}

remaining problems:

  • because of naming-convention ifferences you have to wrap python code so that you can intersept calls to get*() methods. as in c# getters and setters look like Name instead of getName()
  • if there are user visible strings involved, you have to think about translating them
  • checking the python code before deployment

java-bits #1: filedragdrop handler

drop a file from the explorer to a textbox and make the path the text of that textbox:

// imports omitted, dont know why...
public class Foo extends TransferHandler {
 
//...
 
/*
DRAG & DROP
*/
@Override
public boolean importData(JComponent comp, Transferable t) {
// Make sure we have the right starting points
if (!(comp instanceof JTextField)) {
return false;
}
if (!t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
 
// Grab the tree, its model and the root node
JTextField textField = (JTextField) comp;
try {
List data = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
for (Object object : data) {
File f = (File) object;
textField.setText(f.getAbsolutePath());
}
return true;
} catch (UnsupportedFlavorException ufe) {
System.err.println("Ack! we should not be here.\nBad Flavor.");
} catch (IOException ioe) {
System.out.println("Something failed during import:\n" + ioe);
}
return false;
}
 
@Override
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
if (comp instanceof JTextField) {
for (DataFlavor transferFlavor : transferFlavors) {
if (transferFlavor.equals(DataFlavor.javaFileListFlavor)) {
return true;
}
}
return false;
}
return false;
}
}