0

I made a sample application where I want to test swt under osx using maven. I've read hundreds of articles and create the display on main thread, but the app throws the same exception.

Could you check my pom file and my sample application?

pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>asdf.abcd</groupId>
    <artifactId>b</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>example</name>

    <dependencies>
        <dependency>
            <groupId>org.eclipse.swt</groupId>
            <artifactId>org.eclipse.swt.cocoa.macosx.x86_64</artifactId>
            <version>4.3</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jface</groupId>
            <artifactId>jface</artifactId>
            <version>3.9.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>

                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <arguments>
                        <argument>-d64</argument>
                        <argument>-XstartOnFirstThread</argument>
                        <argument>-classpath</argument>
                    </arguments>
                    <mainClass>standalone.App</mainClass>
                    <addClasspath>true</addClasspath>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>standalone.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>

    </build>

</project>

exception:

    ###Thread name: standalone.App.main() Thread[standalone.App.main(),5,standalone.App] <-- debug message


***WARNING: Display must be created on main thread due to Cocoa restrictions.
[WARNING] 
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297)
    at java.lang.Thread.run(Thread.java:744)
Caused by: org.eclipse.swt.SWTException: Invalid thread access
    at org.eclipse.swt.SWT.error(Unknown Source)
    at org.eclipse.swt.SWT.error(Unknown Source)
    at org.eclipse.swt.SWT.error(Unknown Source)
    at org.eclipse.swt.widgets.Display.error(Unknown Source)
    at org.eclipse.swt.widgets.Display.createDisplay(Unknown Source)
    at org.eclipse.swt.widgets.Display.create(Unknown Source)
    at org.eclipse.swt.graphics.Device.<init>(Unknown Source)
    at org.eclipse.swt.widgets.Display.<init>(Unknown Source)
    at org.eclipse.swt.widgets.Display.<init>(Unknown Source)
    at org.eclipse.swt.widgets.Display.getDefault(Unknown Source)
    at standalone.App.main(App.java:66)
    ... 6 more

Thanks for the ideas and your time!

flatronka
  • 1,061
  • 25
  • 51

2 Answers2

2

You need to specify the -XstartOnFirstThread option when you run an SWT app on MAc OS X.

greg-449
  • 109,219
  • 232
  • 102
  • 145
  • Thanks for the answer Greg. I did specify on the pom.xml. When you run the command mvn exec:java exec-maven-plugin will run the app with XstartOnFirstThread argument. You can see in the exception first line that the app runs on the main thread. I printed out the thread name. – flatronka May 10 '14 at 17:16
  • That is not what SWT is seeing, the error message is output because `NSThread.isMainThread()` returns false. – greg-449 May 10 '14 at 17:32
  • Thanks Greg! I don't know how is that possible. – flatronka May 10 '14 at 17:54
2

You are using <goal>java</goal> which runs your app in the same JVM that Maven is running in. That means you can't pass JVM arguments when your app is launched because a new JVM is not being created.

You have two options:

1. Pass JVM arguments to the JVM that runs Maven (and which therefore also eventually runs your app). On the Mac, this is accomplished by setting the MAVEN_OPTS environment variable:

export MAVEN_OPTS="-XstartOnFirstThread`
(then run Maven)

In this case you can remove all the <arguments> from your <configuration> section as they are unnecessary and have no effect. You can also remove <addClasspath>.

2. Use <goal>exec</goal> which will run java as a regular shell command, and you can pass all the JVM configuration arguments you want to it:

<goals>
  <goal>exec</goal>
</goals>

In this case you do need all the things you have in <arguments> as well as your actual main class, because it's just another argument to the JVM being run as a shell command. You can also add your classpath in a slightly simpler way:

<executable>java</executable>
<arguments>
   <argument>-XstartOnFirstThread</argument>
   <argument>-classpath</argument>
   <classpath/>
   <argument>standalone.App</argument>
</arguments>

This second option is generally more robust because you don't have to deal with Maven doing weird things to the JVM before running your app.

samskivert
  • 3,694
  • 20
  • 22