Skip to content

Commit

Permalink
Merge pull request #55 from Pyknic/master
Browse files Browse the repository at this point in the history
Fix: #54 Specify a resource bundle encoding in @FXMLView-annotation
  • Loading branch information
roskenet committed Mar 12, 2018
2 parents eae93a7 + 2e2ac0b commit 49238e6
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 51 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
.project
/.settings/
.springBeans
/.idea/
*.iml
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>de.roskenet</groupId>
<artifactId>springboot-javafx-support</artifactId>
<version>2.1.5</version>
<version>2.1.6-SNAPSHOT</version>
<packaging>jar</packaging>

<name>springboot-javafx-support</name>
Expand All @@ -17,7 +17,7 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-framework.version>5.0.0.RELEASE</spring-framework.version>
<spring-boot.version>2.0.0.M6</spring-boot.version>
<spring-boot.version>2.0.0.RELEASE</spring-boot.version>
<spring-boot-javafx-test.version>1.2.0</spring-boot-javafx-test.version>
<slf4j.version>1.7.25</slf4j.version>
</properties>
Expand Down
56 changes: 32 additions & 24 deletions src/main/java/de/felixroske/jfxsupport/AbstractFxmlView.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
package de.felixroske.jfxsupport;

import static java.util.ResourceBundle.getBundle;

import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.MissingResourceException;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;

import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
Expand All @@ -28,6 +10,25 @@
import javafx.scene.Parent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.StageStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.MissingResourceException;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

import static java.util.ResourceBundle.getBundle;

/**
* Base class for fxml-based view classes.
Expand Down Expand Up @@ -403,17 +404,24 @@ final String getFxmlPath() {
* @return the resource bundle
*/
private Optional<ResourceBundle> getResourceBundle(final String name) {
ResourceBundle bundle;

try {
LOGGER.debug("Resource bundle: " + name);
bundle = getBundle(name);
return Optional.of(getBundle(name,
new ResourceBundleControl(getResourceBundleCharset())));
} catch (final MissingResourceException ex) {
LOGGER.debug("No resource bundle could be determined: " + ex.getMessage());
bundle = null;
return Optional.empty();
}

return Optional.ofNullable(bundle);
}

/**
* Returns the charset to use when reading resource bundles as specified in
* the annotation.
*
* @return the charset
*/
private Charset getResourceBundleCharset() {
return Charset.forName(annotation.encoding());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
Expand Down Expand Up @@ -44,7 +42,11 @@ public abstract class AbstractJavaFxApplicationSupport extends Application {
private static List<Image> icons = new ArrayList<>();
private final List<Image> defaultIcons = new ArrayList<>();

private final BooleanProperty appCtxLoaded = new SimpleBooleanProperty(false);
private final CompletableFuture<Runnable> splashIsShowing;

protected AbstractJavaFxApplicationSupport() {
splashIsShowing = new CompletableFuture<>();
}

public static Stage getStage() {
return GUIState.getStage();
Expand Down Expand Up @@ -118,9 +120,9 @@ private void loadIcons(ConfigurableApplicationContext ctx) {
public void init() throws Exception {
// Load in JavaFx Thread and reused by Completable Future, but should no be a big deal.
defaultIcons.addAll(loadDefaultIcons());
CompletableFuture.supplyAsync(() -> {
return SpringApplication.run(this.getClass(), savedArgs);
}).whenComplete((ctx, throwable) -> {
CompletableFuture.supplyAsync(() ->
SpringApplication.run(this.getClass(), savedArgs)
).whenComplete((ctx, throwable) -> {
if (throwable != null) {
LOGGER.error("Failed to load spring application context: ", throwable);
Platform.runLater(() -> showErrorAlert(throwable));
Expand All @@ -130,6 +132,8 @@ public void init() throws Exception {
launchApplicationView(ctx);
});
}
}).thenAcceptBothAsync(splashIsShowing, (ctx, closeSplash) -> {
Platform.runLater(closeSplash);
});
}

Expand All @@ -155,25 +159,13 @@ public void start(final Stage stage) throws Exception {
splashStage.show();
}

final Runnable showMainAndCloseSplash = () -> {
splashIsShowing.complete(() -> {
showInitialView();
if (AbstractJavaFxApplicationSupport.splashScreen.visible()) {
splashStage.hide();
splashStage.setScene(null);
}
};

synchronized (this) {
if (appCtxLoaded.get()) {
// Spring ContextLoader was faster
Platform.runLater(showMainAndCloseSplash);
} else {
appCtxLoaded.addListener((ov, oVal, nVal) -> {
Platform.runLater(showMainAndCloseSplash);
});
}
}

});
}


Expand All @@ -199,7 +191,6 @@ private void showInitialView() {
*/
private void launchApplicationView(final ConfigurableApplicationContext ctx) {
AbstractJavaFxApplicationSupport.applicationContext = ctx;
appCtxLoaded.set(true);
}

/**
Expand Down
14 changes: 10 additions & 4 deletions src/main/java/de/felixroske/jfxsupport/FXMLView.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package de.felixroske.jfxsupport;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import org.springframework.stereotype.Component;

import javafx.stage.StageStyle;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* The annotation {@link FXMLView} indicates a class to be used in the context
Expand Down Expand Up @@ -38,6 +36,14 @@
* @return the string of such resource bundle.
*/
String bundle() default "";

/**
* The encoding that will be sued when reading the {@link #bundle()} file.
* The default encoding is ISO-8859-1.
*
* @return the encoding to use when reading the resource bundle
*/
String encoding() default "ISO-8859-1";

/**
* The default title for this view for modal.
Expand Down
68 changes: 68 additions & 0 deletions src/main/java/de/felixroske/jfxsupport/ResourceBundleControl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package de.felixroske.jfxsupport;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

import static java.util.Objects.requireNonNull;

/**
* Control that uses a custom {@link Charset} when reading resource bundles,
* compared to the default charset which is ISO-8859-1.
*
* @author Emil Forslund
* @since 2.1.6
*/
public final class ResourceBundleControl extends ResourceBundle.Control {

private final Charset charset;

public ResourceBundleControl(Charset charset) {
this.charset = requireNonNull(charset);
}

@Override
public ResourceBundle newBundle(
final String baseName,
final Locale locale,
final String format,
final ClassLoader loader,
final boolean reload)
throws IllegalAccessException, InstantiationException, IOException {

final String bundleName = toBundleName(baseName, locale);
final String resourceName = toResourceName(bundleName, "properties");

ResourceBundle bundle = null;
InputStream stream = null;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
} else {
stream = loader.getResourceAsStream(resourceName);
}

if (stream != null) {
try {
bundle = new PropertyResourceBundle(new InputStreamReader(
stream, charset));
} finally {
stream.close();
}
}

return bundle;
}
}

0 comments on commit 49238e6

Please sign in to comment.