Run a simple Cascading program in local mode - hadoop

I am struggling to get this simple cascading program to run. For some reason it does nothing. Least I would expect it to print the records. Any help would be appreciated.
package com.myLearning.cascading;
import cascading.flow.Flow;
import cascading.flow.FlowDef;
import cascading.flow.local.LocalFlowConnector;
import cascading.operation.Debug;
import cascading.operation.expression.ExpressionFilter;
import cascading.pipe.Each;
import cascading.pipe.Pipe;
import cascading.scheme.Scheme;
import cascading.scheme.local.TextDelimited;
import cascading.tap.SinkMode;
import cascading.tap.Tap;
import cascading.tap.local.FileTap;
import cascading.tuple.Fields;
public class operations_example
{
public static void main(String[] args)
{
Scheme sourceScheme = new TextDelimited(new Fields("username", "age"), true, ",");
String sourcePath = "C:/Users/Desktop/cascading/data/names.txt";
Tap sourceTap = new FileTap(sourceScheme, sourcePath);
Scheme targetScheme = new TextDelimited(new Fields("username", "age"), true, ",");
String targetPath = "C:/Users/Desktop/cascading/data/output2.txt";
Tap targetTap = new FileTap(targetScheme, targetPath, SinkMode.REPLACE);
Pipe dataPipe = new Pipe("data");
dataPipe = new Each(dataPipe, new Debug());
ExpressionFilter filter = new ExpressionFilter("age >= 30", Integer.TYPE);
dataPipe = new Each( dataPipe,new Fields("username","age"), filter);
FlowDef flowdef = FlowDef.flowDef().
addSource(dataPipe, sourceTap).
addTailSink(dataPipe, targetTap);
Flow flow = new LocalFlowConnector().connect(flowdef);
flow.stop();
}
}

You didn't execute the flow.
After the flow is created, call either complete() (blocking) or start() to execute it. Calling stop() is not going to execute the flow.
http://docs.cascading.org/impatient/impatient1.html
http://docs.cascading.org/cascading/1.2/javadoc/cascading/flow/Flow.html#complete()

Related

When using the SWT_AWT bridge I cannot quit app using `Command` + `q`

I'm trying to make a application that rely on SWT (not the Eclipse Workbench) use Swing component, however I noticed that just adding an SWT_AWT frame prevent the use of the shortcut command+q, and I'm not sure why or how to work around this.
I'm developing on an Intel macOs (but depending on your platform so adapt you dependencies)
org.eclipse.platform:org.eclipse.swt.cocoa.macosx.x86_64:3.120.0
Here's the reproducer:
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class SWTKeyLogger implements Listener{
public static void main(String[] args) {
Display.setAppName("SWT AWT Bridge reproducer");
var display = new Display();
var shell = new Shell(display, SWT.CLOSE | SWT.MIN | SWT.RESIZE | SWT.TITLE | SWT.BORDER);
shell.setSize(400, 200);
shell.setText("Press Key on the blank window");
Listener listener = e -> System.out.println("[SWT] " + e.type == SWT.KeyDown ? "Key Down" : "Key Up");
var swingComposite = new Composite(shell, SWT.EMBEDDED);
swingComposite.setLayout(new GridLayout(1, true));
swingComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
swingComposite.addListener(SWT.KeyDown, listener);
swingComposite.addListener(SWT.KeyUp, listener);
var frame = SWT_AWT.new_Frame(swingComposite);
frame.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
System.out.println("[AWT] Key released");
}
});
}
}
When runing the above code typing command+q doesn't exit the application, instead it hangs, and it may have to be forcefully terminated.
The listener installed on the AWT frame however report the keys, but not the SWT liteners.
And removing the frame make things work again, i.e. typing command+q terminate the application. And the SWT listeners on the composite report the keys.
- var frame = SWT_AWT.new_Frame(swingComposite);
- frame.addKeyListener(new KeyAdapter() {
- #Override
- public void keyReleased(KeyEvent e) {
- System.out.println("[AWT] Key released");
- }
- });
Thanks for any guidance.

JavaFX Media Player - Binding Progress bar with Media Player (Mac m1 Silicon)

I want to update Progress Bar with Media Player Playing. But, after start playing my progressBar fill 100% within one second while the media is 15 seconds - 5 minutes long. I can't figure out the cause.
My codes are as follows:
public static ProgressBar progress = new ProgressBar();
ObjectBinding<TimeElapsed> elapsedBinding =createElapsedBindingByBindingsAPI(player);
DoubleBinding elapsedDoubleBinding =createDoubleBindingByBindingsAPI(elapsedBinding);
progress.progressProperty().bind(elapsedDoubleBinding);
And The methods are :
public static #NotNull ObjectBinding<TimeElapsed> createElapsedBindingByBindingsAPI(
final #NotNull MediaPlayer player
) {
return Bindings.createObjectBinding(
new Callable<TimeElapsed>() {
#Override
public TimeElapsed call() throws Exception {
return new TimeElapsed(player.getCurrentTime());
}
},
player.currentTimeProperty()
);
}
public static #NotNull DoubleBinding createDoubleBindingByBindingsAPI(
final ObjectBinding<TimeElapsed> elapsedBinding
) {
return Bindings.createDoubleBinding(
new Callable<Double>() {
#Override
public Double call() throws Exception {
return elapsedBinding.getValue().getElapsed();
}
},
elapsedBinding
);
}
And the TimeElapsed class :
static class TimeElapsed {
private final double elapsed;
TimeElapsed(#NotNull Duration duration) {
elapsed = duration.toSeconds();
}
public double getElapsed() {
return elapsed;
}
}
So, what's the code changes that 1) update the progressBar with Playing, and 2) seek the song with progress bar clicked or dragged?
The progress of a ProgressBar should be, when determinate, between the values of 0.0 and 1.0 (inclusive). This means you should be dividing the current time by the total duration to get the progress and bind the progress property of the bar to that value. Note that the duration of a Media is observable and is pretty much guaranteed to be set some time after it was instantiated.
As for being able to seek when the progress bar is clicked or dragged, the simplest way—which is what I show in the example below—is to add a MOUSE_CLICKED and a MOUSE_DRAGGED handler to the progress bar, determine the ratio between the mouse's x position and the bar's width, and then seek the calculated time. Unfortunately, this setup may not exactly match up with the visuals of the progress bar because the actual "bar" is smaller than the entire space taken up by the node (at least with default styling). You would probably have to create your own control if you want "pixel perfect" behavior.
Here is a minimal example demonstrating what's discussed above:
import java.util.Optional;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
var mediaView = new MediaView();
var progressBar = new ProgressBar();
progressBar.setMaxWidth(Double.MAX_VALUE);
StackPane.setAlignment(progressBar, Pos.BOTTOM_CENTER);
StackPane.setMargin(progressBar, new Insets(10));
var root = new StackPane(mediaView, progressBar);
primaryStage.setScene(new Scene(root, 1000, 650));
primaryStage.setTitle("Video Progress Demo");
primaryStage.show();
chooseMediaFile(primaryStage)
.ifPresentOrElse(
uri -> {
var media = new Media(uri);
var mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
mediaView.setMediaPlayer(mediaPlayer);
bindProgress(mediaPlayer, progressBar);
addSeekBehavior(mediaPlayer, progressBar);
},
Platform::exit);
}
private void bindProgress(MediaPlayer player, ProgressBar bar) {
var binding =
Bindings.createDoubleBinding(
() -> {
var currentTime = player.getCurrentTime();
var duration = player.getMedia().getDuration();
if (isValidDuration(currentTime) && isValidDuration(duration)) {
return currentTime.toMillis() / duration.toMillis();
}
return ProgressBar.INDETERMINATE_PROGRESS;
},
player.currentTimeProperty(),
player.getMedia().durationProperty());
bar.progressProperty().bind(binding);
}
private void addSeekBehavior(MediaPlayer player, ProgressBar bar) {
EventHandler<MouseEvent> onClickAndOnDragHandler =
e -> {
var duration = player.getMedia().getDuration();
if (isValidDuration(duration)) {
var seekTime = duration.multiply(e.getX() / bar.getWidth());
player.seek(seekTime);
e.consume();
}
};
bar.addEventHandler(MouseEvent.MOUSE_CLICKED, onClickAndOnDragHandler);
bar.addEventHandler(MouseEvent.MOUSE_DRAGGED, onClickAndOnDragHandler);
}
private boolean isValidDuration(Duration d) {
return d != null && !d.isIndefinite() && !d.isUnknown();
}
private Optional<String> chooseMediaFile(Stage owner) {
var chooser = new FileChooser();
chooser
.getExtensionFilters()
.add(new FileChooser.ExtensionFilter("Media Files", "*.mp4", "*.mp3", "*.wav"));
var file = chooser.showOpenDialog(owner);
return Optional.ofNullable(file).map(f -> f.toPath().toUri().toString());
}
}

error in projecting a shapefile from epsg:4326 to epsg:32056

I have been trying to change the projection of Shapefile from one coordinate reference system to other. The shapefile I have used has EPSG:4326 as its reference system and I need to change it to EPSG:32056.
I am using Geotools API-20.0 for the same.
I have already tried various methods available in the geotools like using ReprojectingFeatureCollection, use of JTS, use of Query API to convert the shapefile directly to the other coordinate reference system
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;
import javax.swing.SwingWorker;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFactorySpi;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureWriter;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.CRS;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.geotools.referencing.factory.gridshift.GridShiftLocator;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.JProgressWindow;
import org.geotools.swing.action.SafeAction;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.locationtech.jts.geom.Envelope;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureVisitor;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.FeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.util.ProgressListener;
import com.vividsolutions.jts.geom.Geometry;
public class CRSLab {
private File sourceFile;
private SimpleFeatureSource featureSource;
private MapContent map;
public static void main(String[] args) throws Exception {
CRSLab lab = new CRSLab();
lab.displayShapefile();
}
// docs end main
/**
* This method:
* <ol type="1">
* <li>Prompts the user for a shapefile to display
* <li>Creates a JMapFrame with custom toolbar buttons
* <li>Displays the shapefile
* </ol>
*/
// docs start display
private void displayShapefile() throws Exception {
sourceFile = JFileDataStoreChooser.showOpenFile("shp", null);
if (sourceFile == null) {
return;
}
FileDataStore store = FileDataStoreFinder.getDataStore(sourceFile);
featureSource = store.getFeatureSource();
// Create a map context and add our shapefile to it
map = new MapContent();
Style style = SLD.createSimpleStyle(featureSource.getSchema());
Layer layer = new FeatureLayer(featureSource, style);
map.layers().add(layer);
// Create a JMapFrame with custom toolbar buttons
JMapFrame mapFrame = new JMapFrame(map);
mapFrame.enableToolBar(true);
mapFrame.enableStatusBar(true);
JToolBar toolbar = mapFrame.getToolBar();
toolbar.addSeparator();
toolbar.add(new JButton(new ValidateGeometryAction()));
toolbar.add(new JButton(new ExportShapefileAction()));
// Display the map frame. When it is closed the application will exit
mapFrame.setSize(800, 600);
mapFrame.setVisible(true);
}
// docs end display
// docs start export
private void exportToShapefile() throws Exception {
SimpleFeatureType schema = featureSource.getSchema();
JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
chooser.setDialogTitle("Save reprojected shapefile");
chooser.setSaveFile(sourceFile);
int returnVal = chooser.showSaveDialog(null);
if (returnVal != JFileDataStoreChooser.APPROVE_OPTION) {
return;
}
File file = chooser.getSelectedFile();
if (file.equals(sourceFile)) {
JOptionPane.showMessageDialog(null, "Cannot replace " + file);
return;
}
// set up the math transform used to process the data
CoordinateReferenceSystem dataCRS = schema.getCoordinateReferenceSystem();
CoordinateReferenceSystem worldCRS = CRS.decode("EPSG:32056", true);// map.getCoordinateReferenceSystem();
boolean lenient = true; // allow for some error due to different datums
MathTransform transform = CRS.findMathTransform(dataCRS, worldCRS, lenient);
// grab all features
SimpleFeatureCollection featureCollection = featureSource.getFeatures();
// And create a new Shapefile with a slight modified schema
DataStoreFactorySpi factory = new ShapefileDataStoreFactory();
Map<String, Serializable> create = new HashMap<String, Serializable>();
create.put("url", file.toURI().toURL());
create.put("create spatial index", Boolean.TRUE);
DataStore dataStore = factory.createNewDataStore(create);
SimpleFeatureType featureType = SimpleFeatureTypeBuilder.retype(schema, worldCRS);
dataStore.createSchema(featureType);
String createdName = dataStore.getTypeNames()[0];
// carefully open an iterator and writer to process the results
Transaction transaction = new DefaultTransaction("Reproject");
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriterAppend(createdName,
transaction);
SimpleFeatureIterator iterator = featureCollection.features();
try {
int counter = 0;
while (iterator.hasNext()) {
// copy the contents of each feature and transform the geometry
SimpleFeature feature = iterator.next();
SimpleFeature copy = writer.next();
org.locationtech.jts.geom.Geometry geometry = (org.locationtech.jts.geom.Geometry) feature
.getDefaultGeometry();
org.locationtech.jts.geom.Geometry geometry2 = JTS.transform(geometry, transform);
System.out.println(geometry.isSimple() && geometry2.isSimple());
// if (geometry2.isValid()) {
copy.setAttributes(feature.getAttributes());
counter++;
copy.setDefaultGeometry(geometry2);
writer.write();
// }
}
transaction.commit();
System.out.println("valid geometries : " + counter);
JOptionPane.showMessageDialog(null, "Export to shapefile complete");
} catch (Exception problem) {
problem.printStackTrace();
transaction.rollback();
JOptionPane.showMessageDialog(null, "Export to shapefile failed");
} finally {
writer.close();
iterator.close();
transaction.close();
}
}
// docs end export
// docs start validate
private int validateFeatureGeometry(ProgressListener progress) throws Exception {
final SimpleFeatureCollection featureCollection = featureSource.getFeatures();
// Rather than use an iterator, create a FeatureVisitor to check each
// fature
class ValidationVisitor implements FeatureVisitor {
public int numInvalidGeometries = 0;
public void visit(Feature f) {
SimpleFeature feature = (SimpleFeature) f;
Geometry geom = (Geometry) feature.getDefaultGeometry();
if (geom != null && !geom.isValid()) {
numInvalidGeometries++;
System.out.println("Invalid Geoemtry: " + feature.getID());
}
}
}
ValidationVisitor visitor = new ValidationVisitor();
// Pass visitor and the progress bar to feature collection
featureCollection.accepts(visitor, progress);
return visitor.numInvalidGeometries;
}
// docs end validate
// docs start export action
class ExportShapefileAction extends SafeAction {
ExportShapefileAction() {
super("Export...");
putValue(Action.SHORT_DESCRIPTION, "Export using current crs");
}
public void action(ActionEvent e) throws Throwable {
exportToShapefile();
}
}
// docs end export action
/**
* This class performs the task of checking that the Geometry of each
* feature is topologically valid and reports on the results. It also
* supplies the name and tool tip.
*/
// docs start validate action
class ValidateGeometryAction extends SafeAction {
ValidateGeometryAction() {
super("Validate geometry");
putValue(Action.SHORT_DESCRIPTION, "Check each geometry");
}
public void action(ActionEvent e) throws Throwable {
int numInvalid = validateFeatureGeometry(null);
String msg;
if (numInvalid == 0) {
msg = "All feature geometries are valid";
} else {
msg = "Invalid geometries: " + numInvalid;
}
JOptionPane.showMessageDialog(null, msg, "Geometry results", JOptionPane.INFORMATION_MESSAGE);
}
}
// docs end validate action
}
The output obtained after doing projection using Geotools are a lot different than what I used to get from ArcMap of esri. Is there any other transformation that I should perform.
When I try this (with v22.x) all I get is an error as too many points are outside the valid projection error. This is because you are taking a map of the world and reprojecting it to a CRS designed for Wyoming.
It seems that ESRI are being "helpful" and clipping your output to the area of validity (assuming you meant something other than EPSG:32056). GeoTools assumes that you know what you are doing and doesn't do that, which is why you have all the countries of the world shown in that map.
Here is the output for just the USA, which suggests that the ESRI image you show is a different projection again (look at the 49th parallel).

ScalaFX: Is it possible to define controls in objects other than the application object?

What I am trying to accomplish is: having a ScalaFX application with some nice ordered objects called Buttons, Labels, Checkboxes and so on to keep everything nice and in order.
Here a little example to show what I mean:
package ButtonsAndLabel
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.scene.control.{ Button, Label }
import scalafx.event.ActionEvent
object Main extends JFXApp {
stage = new JFXApp.PrimaryStage {
title = "Test-Program"
scene = new Scene(300, 200) {
val label = new Label("Nothing happened yet") {
layoutX = 20
layoutY = 20
}
val button1 = new Button("Button 1") {
layoutX = 20
layoutY = 50
onAction = (e: ActionEvent) => {
label.text = "B1 klicked"
}
}
val button2 = new Button("Button 2") {
layoutX = 20
layoutY = 80
onAction = (e: ActionEvent) => {
label.text = "B2 klicked"
}
}
content = List(label, button1, button2)
}
}
}
This code shows a window with a label and two buttons, and the buttons change the text of the label.
That works fine.
But when my code grows with a lot more controls, things get messy.
That's why I tried to transfer the controls into other objects (in different files). I've put the label into an object called Labels:
package ButtonsAndLabel
import scalafx.scene.control.Label
import scalafx.event.ActionEvent
object Labels {
val label = new Label("Nothing happened yet") {
layoutX = 20
layoutY = 20
}
}
when I import this into the main-file with
import Labels.label
everything works fine.
But then I try to put the buttons into a Buttons object:
package ButtonsAndLabel
import scalafx.scene.control.Button
import scalafx.event.ActionEvent
import Labels.label
object Buttons {
val button1 = new Button("Button 1") {
layoutX = 20
layoutY = 50
onAction = (e: ActionEvent) => {
label.text = "B1 klicked"
}
}
val button2 = new Button("Button 2") {
layoutX = 20
layoutY = 80
onAction = (e: ActionEvent) => {
label.text = "B2 klicked"
}
}
}
this brings the error message when I try to compile:
[error] found : scalafx.event.ActionEvent => Unit
[error] required: javafx.event.EventHandler[javafx.event.ActionEvent]
[error] onAction = (e: ActionEvent) => {
and now I am stuck, as I don't know any Java.
Does anybody know if it is even possible what I am trying to do?
So far I have not found anything about this on the net. The problem doesn't keep me from writing the program I want, but the last application I wrote was a real mess with all the controls in one file.
Am I overlooking something obvious here?
Any help would be really appreciated.
Firstly, your approach is perfectly OK.
The error you're seeing actually has nothing to do with Java—it's output by the Scala compiler! All it's saying is that it has been supplied one type of element (in this case, a function that takes a scalafx.event.ActionEvent and that returns Unit) when it was expecting another type of element (a javafx.event.EventHandler[javafx.event.ActionEvent] instance, in this case).
ScalaFX is just a set of Scala-friendly wrappers for the JavaFX library; without the implicit conversion functions that convert between the two sets of elements, the Scala compiler will complain about finding ScalaFX elements when it needs JavaFX elements, and vice versa.
The solution is to ensure that the following import is added to each of your ScalaFX source files:
import scalafx.Includes._
(You have this at the top of your main source file, but not the others.)
This will ensure that your ScalaFX ActionEvent handler is converted into the JavaFX equivalent, thereby making your life a little easier.
This is a very common type of error with ScalaFX, which is nearly always fixed by specifying the above import. (If the import doesn't fix your problem, then you will typically have a genuine case of type confusion, in which you just plain used the wrong type of object.)
So, here's what I think your code needs to look like:
Main.scala:
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.scene.Scene
import buttonsandlabel._
object Main extends JFXApp {
stage = new JFXApp.PrimaryStage {
title = "Test-Program"
scene = new Scene(300, 200) {
content = List(Labels.label, Buttons.button1, Buttons.button2)
}
}
}
buttonsandlabel/Labels.scala:
package buttonsandlabel
import scalafx.Includes._
import scalafx.scene.control.Label
object Labels {
val label = new Label("Nothing happened yet") {
layoutX = 20
layoutY = 20
}
}
buttonsandlabel/Buttons.scala:
package buttonsandlabel
import scalafx.Includes._
import scalafx.scene.control.Button
import scalafx.event.ActionEvent
import Labels.label
object Buttons {
val button1 = new Button("Button 1") {
layoutX = 20
layoutY = 50
onAction = (e: ActionEvent) => {
label.text = "B1 klicked"
}
}
val button2 = new Button("Button 2") {
layoutX = 20
layoutY = 80
onAction = (e: ActionEvent) => {
label.text = "B2 klicked"
}
}
}
(Note that package names, by convention, are typically all lowercase.)
One thing that you'll need to be aware of is the JavaFX Application Thread: all of your code that interacts with ScalaFX (or JavaFX) must execute on this thread. If you access ScalaFX/JavaFX from a different thread, you'll get an error exception. (This ensures that all such applications are thread-safe.) If you're unfamiliar with multi-threading, don't worry, ScalaFX initializes your application in such a way that this is fairly trivial. Usually, all that's needed is that your initialization code goes into your main application object's constructor (the object that extends JFXApp).
When you start creating ScalaFX elements in other classes and objects, you need to take extra care. An object is initialized when first referenced. If it is first referenced by code that is not executing on the JavaFX Application Thread, then you'll get thread error exceptions. One possible option is to put such code into def or lazy val members, so that they are only executed when referenced directly.
Alternatively, you may have to invoke your code via scalafx.application.Platform.runLater().
For more information on the JavaFX Application Thread, refer to the JavaFX documentation.

cmd.exe does not show up when it is from AIR(AS3) invoked

When I use AIR to invoke cmd.exe, it doesn't show up, but it appears in Task-Manager. When I pass parameter to cmd.exe, it doesn't react. The code has no problem with invoking notepad.exe or wscript.exe.(There is a button named btn on the stage) Here is my code:
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.filesystem.File;
btn.addEventListener(MouseEvent.CLICK, invokeCmd);
function invokeCmd(e:MouseEvent):void{
if(NativeProcess.isSupported){
btn.label="NativeProcess supported";
var info:NativeProcessStartupInfo = new NativeProcessStartupInfo();
info.executable = new File("C:/Windows/System32/cmd.exe");
var processArg:Vector.<String> = new Vector.<String>();
processArg.push("start dir");
info.arguments = processArg;
var process:NativeProcess = new NativeProcess();
process.start(info);
}
}

Resources