• Feb
    • 20
    • 2012

Porting “First Contact” to Spring

Posted by In Uncategorized 9 comments
This entry is part 10 of 15 in the series Building JEE applications in JavaFX 2.0

In an earlier post we looked at different design patterns for building First Contact, our simple JavaFX-based contact management system. To keep things simple I deliberately avoided using Spring (or Guice) for the dependency injection and instead manually injected all the dependencies. This is great for educational purposes but really we’re doing things the hard way – Spring provides all sorts of magical things for making this easier, so let’s take advantage of them.

We looked at five different design pattern options for implementing First Contact, but moving forward let’s just pick one and work with that. I’m going to go with “Option 4: FXML and the MVP compromise” as it lets us use FXML for the presentation layer, which I think is a big win. Option 5 also uses FXML, but it is based on my third-party framework, JFX Flow and although I’m confident that JFX Flow is a nice little framework to use, I want it to leave it out of the equation at this stage so you can get a good, clean understanding of how everything is working. The pattern used in option 4 is very similar to what Flow expects, so switching between the two should be relatively trivial (and I’ll most likely do a port of our final First Contact app to JFX Flow when we get it all working).

So to give us a base to work off, we’ll make a copy of the source code from option 4, and then we’ll modify this to use Spring for dependency injection. The final source code for this blog can be found at: http://code.google.com/p/jfxee/source/browse/trunk/first-contact/first-contact-spring/.

Step 1: Add Spring dependencies

The first thing we need to do is get hold of the Spring JARs and get them on our classpath. Since we’re using Maven (check out my previous post on using Maven if you haven’t done so already) all we need to do is add the dependencies for the relevant Spring libraries to our pom.xml. Spring is made up of a whole suite of modules that we could use, but our requirements at this stage are quite simple. We just need Spring’s basic ‘context’ module for dependency injection. Since we’re using Spring’s annotation-based configuration (because I hate writing XML if I can avoid it), we’ll also need both the CGLIB module and the standard javax.inject library, which the annotation stuff in Spring makes use of.

We can update our pom.xml to look like this:

<?xml version="1.0"?>
<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>com.zenjava</groupId>
    <artifactId>first-contact-spring</artifactId>
    <name>JFX Contact Management System</name>

    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <!-- JavaFX -->

        <dependency>
            <groupId>com.sun.javafx</groupId>
            <artifactId>javafx</artifactId>
            <version>2.0.beta</version>
            <scope>system</scope>
            <systemPath>C:/apps/javafx/javafx-2.0.2_32bit/rt/lib/jfxrt.jar</systemPath>
        </dependency>

        <!-- Spring and supporting toolkits -->

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.0.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

    </dependencies>

</project>

We’re reaping the rewards of using Maven here – just by adding those few dependencies to the pom.xml, Maven will automatically download the necessary JARs and put them on our application classpath. How easy is that!

Step 2: Simplify the First Contact Application Factory

Without Spring, we had to hand roll our own application factory. If you’ve forgotten what this looked liked, take a moment to look through our old FistContactAppFactory class. In this class we manually created all our beans, kept references to them, and then used setter methods to wire up everything (i.e. give each object access to the other beans it needed). The general pattern was something a little like this:

public class FirstContactApplicationFactory
{
    private SomeObject someObject;

    public SomeObject getSomeObject()
    {
        if (this.someObject == null)
        {
            this.someObject = new SomeObject();
            this.someObject.setSomeOtherObject1(getSomeOtherObject1());
            this.someObject.setSomeOtherObject2(getSomeOtherObject2());
        }
        return this.someObject;
    }

    ...
}

And we repeat this over and over again for each object we want to use. Lot’s of boring, copy-paste code.

With Spring we can get rid of most of this boiler plate code. First we annotate our FirstContactAppFactory class with the @Configuration annotation. This is just a marker, that lets Spring know this class is an application factory capable of providing beans for dependency injection.

Once we’ve done that we can then annotate each of the factory methods with Spring’s @Bean annotation. By doing this, we tell Spring that the resulting object is a bean that can be injected into other classes. We also tell Spring that we want the result of the method to be a singleton (this is the default for all beans in Spring, though you can change it if you want): Spring will then make sure the bean is only created once and the result will be cached and reused for every subsequent method call.

With Spring now doing our singleton caching we can get rid of the manual caching we were doing. Our new pattern looks a little like the following:

@Configuration
public class FirstContactApplicationFactory
{
    @Bean
    public SomeObject getSomeObject()
    {
        SomeObject someObject = new SomeObject();
        someObject.setSomeOtherObject1(getSomeOtherObject1());
        someObject.setSomeOtherObject2(getSomeOtherObject2());
        return someObject;
    }

    ...
}

This has saved us a fair bit of work already, but we can go one step further. Those calls to the setter methods are actually dependency injection, which is what Spring does for us so we can drop those as well (we need to also add some annotations on our Beans for this to work – see the next step). Our new pattern is now as simple as this:

@Configuration
public class FirstContactApplicationFactory
{
    @Bean
    public SomeObject getSomeObject()
    {
        return new SomeObject();
    }

    ...
}

Pretty simple! Below is the source code for the updated FirstContactAppFatcory. All it really does is create all our presenters and return them (using the FXML loader rather than creating a ‘new’ instance, but the pattern is the same). I’ve also dropped the ‘get’ from the method names, this is just a convention thing – Spring tends to leave these off for factory methods (since they are not strictly getters anymore), but you can name the methods whatever you want.

@Configuration
public class FirstContactAppFactory
{
    @Bean
    public MainPresenter mainPresenter()
    {
        return loadPresenter("/fxml/Main.fxml");
    }

    @Bean
    public ContactSearchPresenter contactSearchPresenter()
    {
        return loadPresenter("/fxml/ContactSearch.fxml");
    }

    @Bean
    public ContactDetailPresenter contactDetailPresenter()
    {
        return loadPresenter("/fxml/ContactDetail.fxml");
    }

    @Bean
    public ContactService contactService()
    {
        return new SimpleContactService();
    }

    private <T> T loadPresenter(String fxmlFile)
    {
        try
        {
            FXMLLoader loader = new FXMLLoader();
            loader.load(getClass().getResourceAsStream(fxmlFile));
            return (T) loader.getController();
        }
        catch (IOException e)
        {
            throw new RuntimeException(String.format("Unable to load FXML file '%s'", fxmlFile), e);
        }
    }
}

There’s a whole lot more that Spring can do for us – we are definitely only using the most basic of its features at this stage. For now though, that’s all we need and as you can see it’s made our code significantly simpler and easier to maintain.

Step 3: Inject dependencies using annotations

In the previous step we took away all those explicit setter calls in our factory methods (i.e. the manual dependency injection calls). We need to annotate our beans as well so that Spring knows to inject these classes for us now. For each of our beans, where we were previously calling a set method, we need to annotate the corresponding property instead. In fact, we can get rid of the setter altogether (if you want to leave it in, you can, but I tend to get rid of them) as Spring can access our annotated properties, even if they are private member variables with no getters or setters.

So something like this:

public class MyPresenter
{
    private String myProperty;

    public void setMyProperty(String myProperty)
    {
        this.myProperty = myProperty;
    }

    ...
}

Becomes as simple as this:

public class MyPresenter
{
    @Inject private String myProperty;

    ...
}

Again we’re just removing some of the minor annoying boiler plate code and telling Spring we want it to take care of the dependency injection for us. For some before and after examples, check out the following changes:

Note for long-time Spring users: the @Inject annotation is just the newer standards-based version of @Autowired. They are more or less interchangeable, however using the standards one allows us to change frameworks (e.g. move to Guice) with minimal fuss.

Step 4: Change how the factory is loaded at startup

Our factory and our beans are now all dressed up for the Spring dance, but we’ve still got to kick off the music. In our previous FirstContactApp we were manually instantiating a new instance of our FirstContactAppFactory and then accessing the main presenter by calling getter methods. This isn’t going to give Spring a chance to get in there and do all that magic autowiring stuff for us, so we need to change this slightly.

As you’d expect, the code for this is pretty simple. All we need to do is  use Spring’s AnnotationConfigApplicationContext and let it instantiate our Factory for us so we can then use Spring’s standard bean lookup mechanism to get our fully wired-up beans:

public void start(Stage stage) throws Exception
{
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(FirstContactAppFactory.class);
    MainPresenter mainPresenter = context.getBean(MainPresenter.class);
    mainPresenter.showSearchContacts();
    Scene scene = new Scene(mainPresenter.getView(), 800, 600);
    scene.getStylesheets().add("styles.css");
    stage.setScene(scene);
    stage.setTitle("First Contact - JavaFX Contact Management");
    stage.show();
}

Wrapping it up

That’s all the changes we need to make. If you run your updated FirstContactApp main method, you should see exactly the same GUI as from our previous post. We’ve not changed any of the functionality, just simplified the plumbing and removed a lot of redundant code.

Using Spring to this level has already helped us somewhat but we’ve barely scratched the surface. The main reason I wanted to port this application across is that in my next post I’m going to look at hooking this all up to a database using JPA. Spring is really going to start to pay off in this environment, and after that, when we add Transactions, Remoting and possibly even a dash of Security, we’ll be really making the most of Spring’s power.

Series Navigation<< JavaFX and MavenGoing Remote – JavaFX and Spring Remoting >>

9 Comments

  • Reply
    Naveedur Rahman
    March 19, 2012

    Hi,
    I am getting the below error while running this.

    Adapter validation failed for all adapters
    Mar 19, 2012 7:20:27 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
    INFO: JSR-330 ‘javax.inject.Named’ annotation found and supported for component scanning
    Mar 19, 2012 7:20:27 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
    INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@18f2e35: startup date [Mon Mar 19 19:20:27 IST 2012]; root of context hierarchy
    Mar 19, 2012 7:20:28 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    INFO: JSR-330 ‘javax.inject.Inject’ annotation found and supported for autowiring
    Mar 19, 2012 7:20:28 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c747e8: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,jfxFlowShowcaseApplicationFactory,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,browser,navigationManager,dialogsActivity,navigationActivity,browserInfoActivity,formsActivity,threadingActivity,actvityInfoActivity,homeActivity,navigationManagerInfoActivity,transitionsActivity,resources,fadeTransitionActivity,customTransitionActivity,flyTransitionActivity,errorHandler]; root of factory hierarchy
    Mar 19, 2012 7:20:29 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
    INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c747e8: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,jfxFlowShowcaseApplicationFactory,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,browser,navigationManager,dialogsActivity,navigationActivity,browserInfoActivity,formsActivity,threadingActivity,actvityInfoActivity,homeActivity,navigationManagerInfoActivity,transitionsActivity,resources,fadeTransitionActivity,customTransitionActivity,flyTransitionActivity,errorHandler]; root of factory hierarchy
    Exception in Application start method
    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:601)
    at com.javafx.main.Main.launchApp(Main.java:486)
    at com.javafx.main.Main.main(Main.java:638)
    Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.access$000(Unknown Source)
    at com.sun.javafx.application.LauncherImpl$1.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:722)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘browser’ defined in class com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.zenjava.jfxflow.control.Browser com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.browser()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘homeActivity’ defined in class com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.zenjava.samples.simpleflow.HomeActivity com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.homeActivity()] threw exception; nested exception is com.zenjava.jfxflow.actvity.FxmlLoadException: Unable to load FXML from ‘/fxml/Home.fxml’: fxml.Home cannot be cast to com.zenjava.jfxflow.actvity.HasNode
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:581)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1015)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.(AnnotationConfigApplicationContext.java:73)
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplication.start(JfxFlowShowcaseApplication.java:27)
    at com.sun.javafx.application.LauncherImpl$5.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$4.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$3.run(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(Unknown Source)
    at com.sun.glass.ui.win.WinApplication$2$1.run(Unknown Source)
    … 1 more
    Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.zenjava.jfxflow.control.Browser com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.browser()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘homeActivity’ defined in class com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.zenjava.samples.simpleflow.HomeActivity com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.homeActivity()] threw exception; nested exception is com.zenjava.jfxflow.actvity.FxmlLoadException: Unable to load FXML from ‘/fxml/Home.fxml’: fxml.Home cannot be cast to com.zenjava.jfxflow.actvity.HasNode
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:169)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:570)
    … 20 more
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘homeActivity’ defined in class com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.zenjava.samples.simpleflow.HomeActivity com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.homeActivity()] threw exception; nested exception is com.zenjava.jfxflow.actvity.FxmlLoadException: Unable to load FXML from ‘/fxml/Home.fxml’: fxml.Home cannot be cast to com.zenjava.jfxflow.actvity.HasNode
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:581)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1015)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:292)
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory$$EnhancerByCGLIB$$176f66bb.homeActivity()
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.browser(JfxFlowShowcaseApplicationFactory.java:32)
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory$$EnhancerByCGLIB$$176f66bb.CGLIB$browser$0()
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory$$EnhancerByCGLIB$$176f66bb$$FastClassByCGLIB$$488b075e.invoke()
    at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:280)
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory$$EnhancerByCGLIB$$176f66bb.browser()
    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:601)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:149)
    … 21 more
    Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.zenjava.samples.simpleflow.HomeActivity com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.homeActivity()] threw exception; nested exception is com.zenjava.jfxflow.actvity.FxmlLoadException: Unable to load FXML from ‘/fxml/Home.fxml’: fxml.Home cannot be cast to com.zenjava.jfxflow.actvity.HasNode
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:169)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:570)
    … 42 more
    Caused by: com.zenjava.jfxflow.actvity.FxmlLoadException: Unable to load FXML from ‘/fxml/Home.fxml’: fxml.Home cannot be cast to com.zenjava.jfxflow.actvity.HasNode
    at com.zenjava.jfxflow.actvity.FxmlLoader.load(FxmlLoader.java:71)
    at com.zenjava.jfxflow.actvity.FxmlLoader.load(FxmlLoader.java:32)
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory.homeActivity(JfxFlowShowcaseApplicationFactory.java:56)
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory$$EnhancerByCGLIB$$176f66bb.CGLIB$homeActivity$8()
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory$$EnhancerByCGLIB$$176f66bb$$FastClassByCGLIB$$488b075e.invoke()
    at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:280)
    at com.zenjava.samples.simpleflow.JfxFlowShowcaseApplicationFactory$$EnhancerByCGLIB$$176f66bb.homeActivity()
    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:601)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:149)
    … 43 more
    Caused by: java.lang.ClassCastException: fxml.Home cannot be cast to com.zenjava.jfxflow.actvity.HasNode
    at com.zenjava.jfxflow.actvity.FxmlLoader.load(FxmlLoader.java:60)
    … 55 more
    Java Result: 1

    kindly help on this….

    • Reply
      Rob
      February 22, 2013

      We are having the exact same issue > using Spring + JavaFX when running the fx application remotely. Our client fails to load our FXML files. Have you been able to resolve the issue? We can’t seem to find any other resources on the web that share the same issue.

  • Reply
    August 16, 2012

    Man, you are doing a good work! Your posts are so simple and useful! I really like!

    I dont want to use a PURE annotation confiugration, as I will build an desktop application with JavaFX 2.0 on Eclipse OSGi Virgo Container. Do you have any sugestions in how to load spring managed containers? A custom Bean Factory? An abstract Bean with a bean-factory definition that will return the FXML Controller? I dont wanna to access my ApplicationContext inside presenters in order to wire beans, etc

    Thanks!!!!!

  • Reply
    zonski Author
    August 17, 2012

    I’m not sure exactly what you are trying to achieve. I haven’t used OSGi so not sure exactly how that influences things.

    If you don’t want to use annotations for the Spring Context that is fine, you can use an XML based configuration file and load that in the normal Spring way. Basically the FirstContactAppFactory would be thrown away and replaced by an XML file with all your controllers in it.

    I’m not sure that’s what you are after, but you’ll need to provide a bit more info about your problem for anything else.

  • Reply
    John W.
    August 25, 2012

    I compiled with maven 3.0.3 your first-contact-spring project. When running the the target/jar I got an error

    “no main manifest attribute, in first-contact-spring-1.0-SNAPSHOT.jar”

    I also configured the pom.xml according to your playground/pom.xml but still could not create the MANIFEST.MF with the main program entry. Could you provide the pom.xml main snippet for this?

    -john

  • Reply
    zonski Author
    September 2, 2012

    Hi John,

    Unfortunately this blog post only covers how to use Maven to setup your build/development environment. Due mostly to a lack of love towards Maven from the JFX team there is still no true Maven way to assemble your actual deployable bundle via Maven. You have to fall out to ANT at this stage.

    Here’s a fairly old forum post I wrote on this a while back:
    https://forums.oracle.com/forums/thread.jspa?messageID=9931337&#9931337

    Someone may have improved on this so I would suggest searching the forums for newer ‘Maven’ posts just in case.

    When they finally sort out the legal and technical issues with co-bundling issues with JFX and the JRE then we will be in a better position to actually build a pure Maven plugin that does all this. Feel free to voice your concerns to the JFX team on the forum, in JIRA and/or on the openjfx mailing list if this is important to you (I’ve been voicing my concerns on this one for many months now).

    Probably the most useful place to comment would be:
    http://javafx-jira.kenai.com/browse/RT-15732

Leave a Comment