Package private beans

Thinking about separation in my code the question of package private beans popped up. The general pattern here is to have interfaces defined. The implementing classes however are package private. Instances are generated through a factory. I looked around to find some documentation how this can be done with a Spring context, but found none, so here it is. Special interest is the Spring configuration with Java.

The package private beans are annotated and the classpath is scanned. These classes are discovered, as this basically involves reflection. The beans however cannot be instantiated in the configuration, as the beans are not visible in the package of the configuration class. This is where the factory comes in. The factory resides in the same package as the beans however is a public @Service and so is available in the application context.

I tried this out with two beans:

package ch.sahits.spring.bean.internal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Random;

@Component
class PackagePrivateBean {
    @Autowired
    private Random rnd;

    public Random getRnd() {
        return rnd;
    }
}
package ch.sahits.spring.bean.internal;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope(value = "prototype")
class PackagePrivatePrototype {
    private final int a;

    public PackagePrivatePrototype(int a) {
        this.a = a;
    }

    public int getA() {
        return a;
    }
}

The configuration looks like this:

 

package ch.sahits.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.Random;

@Configuration
@ComponentScan(basePackages = {"ch.sahits.spring.bean.internal"})
public class PackagePrivateSpringConfiguration {
    @Bean
    public Random rnd() {
        return new Random();
    }

}

The factory:

package ch.sahits.spring.bean.internal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Service
public class PackagePrivateBeanFactory {

    @Autowired
    private ApplicationContext context;

    public PackagePrivateBean getBean() {
        return context.getBean(PackagePrivateBean.class);
    }

    public PackagePrivatePrototype getBean(int i) {
        Object[] args = new Object[]{Integer.valueOf(i)};
        return (PackagePrivatePrototype)context.getBean("packagePrivatePrototype", args);
    }
}

I tested this with a Test-Case:

package ch.sahits.spring;

import ch.sahits.spring.bean.internal.PackagePrivateBeanFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;

import static org.junit.Assert.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=PackagePrivateSpringConfiguration.class, loader=AnnotationConfigContextLoader.class)
public class PrivatePackageConfigurationTest {
    @Autowired
    private PackagePrivateBeanFactory factory;

    @Test
    public void factoryShouldNotBeNull() {
        assertNotNull(factory);
    }

    @Test
    public void packagePrivateComponentShouldNotBeNull() {
        Object o = factory.getBean();
        assertNotNull(o);
    }

    @Test
    public void packagePrivatePrototypeShouldNotBeNull() {
        Object o = factory.getBean(47);
        assertNotNull(o);
    }
}

The curious thing is that the PackagePrivateBean is by default of scope Singleton and thereby has to be created on application context startup. As this happens through reflection of the default constructor this is even possible even though the bean itself is not visible and can therefore not be defined through the configuration class. This is a case, where you get an instance through the package scan that cannot be done through explicit definition. This applies in the same manner for XML configuration. Defining a package private bean in XML would cause a runtime exception when reading the XML application context.

Shutting down Spring backed JavaFX application

This is just another short tip on how to combine JavaFX and the Spring Framework. These two technologies do not work perfectly together, but they can be made to cooperate. One of the two is the lead, meaning one is initialized first from the main method and therefore controls the lifecycle of the application. In my case this is the Spring framework as the user interface is optional. However I still want to handle the case where the user interface is closed (or the menu point quit is selected) and this should also shut down the application context of Spring.

There are three steps that should be taken:

  • Register the shutdown hooks for your application context. This has nothing to do with canceling the application in a controlled manner. This case covers things like Ctrl+C or kill -9.
((AbstractApplicationContext)context).registerShutdownHook();
  • Override the stop method of Application. When closing the application window, the stop method is called. You will want to hook into this method to signal the spring context that his end has come.
    @Override
    public void stop() throws Exception {
        System.out.println("Stopping the UI Application");

        stopUIApplicationContext();
        super.stop();
    }

In my case I used Guava’s EventBus to signal the context.

  • Finally in your code handling the context end it.
((AbstractApplicationContext)context).close();

That’s it, folks!

Custom Spring scope done right

You can define your own Spring Scope. One thing to consider is that the beans that are defined in a scope must somehow be backed by a store. For the singlton scope this is the application context itself, for a session scope it is the session, for a request scope it is the request. With this setup the beans lifecycle is bound to the lifecycle of the backing store, e.g. when a session terminates it is deleted and with it all the corresponding beans.

There are other examples out there that implement a custom scope by implementing the store in the scope. This then requires that the lifecycle has to be managed from the outside. So let’s do this the right way:

  • We want a scope that matches the lifecycle of a dialog. The dialog is opened some content is displayed, some work is done and finally the dialog is closed.
  • The application code should not be polluted with logic to manage the bean life cycle of the scope.

„Custom Spring scope done right“ weiterlesen

Replicable State with Spring

Recently I have come across a problem, which does not have an elegant solution. Imagine you have a setup like this:

  • Nice little (or not so little) application based on the Spring-Framework
  • Lots of utilities and services that are waiting to be injected into something
  • Services/Components which represent singletons and do have state, all managed through Spring
  • Application State uses these services
  • Application State is replicated: for example loaded from a file before injected with the Spring Beans
  • Application State is ‚updated‘: the state is changed from the outside after it is created (think repeated loading replacing the old state)

If it were not for the last point the preferred solution would be to implement you own BeanFactory, create a new Spring context into which the newly created beans are pushed into and make it a child context of the already existing context. The BeanFactory would use the existing context to do the wiring on the newly created beans.

However when this replicating happens repeatedly you would end up with a huge context hierarchy, over which you have no control. What you want instead is some Hot soaping of the state in the existing context, but we all know how well these things work.

In my concrete use case the application consists of multiple parts, which do not run necessarily in the same VM, however share the same state. Another approach would be to have the state not managed by Spring. This however would complicate the application code considerably as the whole state would have to be passed around everywhere and each part would have to navigate through the model hierarchy to retrieve their required components.

So here is what I have come up with:

„Replicable State with Spring“ weiterlesen

TextFlow with JavaFX 2

When ever you want to display a large portion of text in your application the Text node is your friend. Text allows you to define a wrapping width and thereby allows nice multyline text without letting you bother about the line break.

However what when your text is not that simple? It might contain portions that are differently formatted? Links? Or even icons?

JavaFX 8 has a solution for this: TextFlow. If you are however stuck with JavaFX 2 for whatever reason, there is simple workaround: pack all the Nodes into a FlowPane and define the wrapping width to be the preferred width.

public class DecoratedText extends FlowPane {

    private IntegerProperty wrappingWidth;
    private ReadOnlyObjectProperty<Font> font;
    public DecoratedText(Font font) {
        super(Orientation.HORIZONTAL);
        wrappingWidth = new SimpleIntegerProperty(this, "wrappingWidth", 0);
        getStylesheets().add(getClass().getResource(getClass().getSimpleName()+".css").toExternalForm());
        this.font = new SimpleObjectProperty<>(this, "font", font);
        prefWidthProperty().bindBidirectional(wrappingWidth);
    }

    /**
     * Append text. If the text represents a paragraph (indicated by '\n'), it
     * is not broken up into its parts.
     * @param text
     */
    public void append(String text) {
        if (text.endsWith("\n")) {
            Text decoText = new Text(text);
            //decoText.getStyleClass().add("decoratedText-text");
            decoText.setFont(font.get());
            decoText.wrappingWidthProperty().bind(wrappingWidth);
            getChildren().add(decoText);
        } else {
            String[] parts = text.split(" ");
            for (String part : parts) {
                Text decoText = new Text(part+" ");
                //decoText.getStyleClass().add("decoratedText-text");
                decoText.setFont(font.get());
                getChildren().add(decoText);
            }
        }
    }

    /**
     * Append a control.
     * @param control
     */
    public void append(Node control) {
         getChildren().add(control);
    }

    public int getWrappingWidth() {
        return wrappingWidth.get();
    }

    public IntegerProperty wrappingWidthProperty() {
        return wrappingWidth;
    }

    public void setWrappingWidth(int wrappingWidth) {
        this.wrappingWidth.set(wrappingWidth);
    }
}

The idea here is to leave text blocks which represent a paragraph by themselves as Text node. However if the paragraph contains some other node, it is splitt up into words. Thereby delegating the wrapping functionality to the underlying FlowPane.

While this solution here is not particularly sophisticated, it suffices my needs. Nevertheless I will replace it with TextFlow as soon as I migrate to Java 8.