Java tutorial
/* GRANITE DATA SERVICES Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. This file is part of Granite Data Services. Granite Data Services is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Granite Data Services is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see <http://www.gnu.org/licenses/>. */ package com.wineshop.client; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Dialogs; import javafx.scene.control.Dialogs.DialogOptions; import javafx.scene.control.Dialogs.DialogResponse; import javafx.scene.control.Label; import javafx.stage.Stage; import javax.inject.Inject; import org.granite.client.javafx.tide.JavaFXApplication; import org.granite.client.javafx.tide.JavaFXServerSessionStatus; import org.granite.client.javafx.tide.ManagedEntity; import org.granite.client.javafx.tide.TideFXMLLoader; import org.granite.client.javafx.tide.collections.PagedQuery; import org.granite.client.javafx.tide.spring.Identity; import org.granite.client.tide.ContextManager; import org.granite.client.tide.data.Conflicts; import org.granite.client.tide.data.DataConflictListener; import org.granite.client.tide.data.DataObserver; import org.granite.client.tide.data.EntityManager; import org.granite.client.tide.server.ExceptionHandler; import org.granite.client.tide.server.ServerSession; import org.granite.client.tide.server.SimpleTideResponder; import org.granite.client.tide.server.TideFaultEvent; import org.granite.client.tide.server.TideResultEvent; import org.granite.client.tide.spring.SpringContextManager; import org.granite.client.tide.validation.ValidationExceptionHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import com.wineshop.client.entities.Vineyard; import com.wineshop.client.services.VineyardRepository; /** * * @author william */ public class Main extends Application { private static final Logger log = LoggerFactory.getLogger(Main.class); /** * Main class that lauches the JavaFX app */ public static void main(String[] args) { Application.launch(Main.class, args); } /** * Spring context configuration * @author william * */ @Configuration public static class Config { /** * Integration with the Spring context and JavaFX */ @Bean public SpringContextManager contextManager() { return new SpringContextManager(new JavaFXApplication()); } /** * Configuration for server remoting and messaging */ @Bean(initMethod = "start", destroyMethod = "stop") public ServerSession serverSession() throws Exception { ServerSession serverSession = new ServerSession("/shop-admin-javafx", "localhost", 8080); serverSession.addRemoteAliasPackage("com.wineshop.client.entities"); return serverSession; } /** * Identity component that integrates with server-side Spring Security */ @Bean public Identity identity(ServerSession serverSession) throws Exception { return new Identity(serverSession); } /** * Integration with server-side Bean Validation constraint exceptions */ @Bean public ExceptionHandler validationExceptionHandler() { return new ValidationExceptionHandler(); } /** * Defines the main application as a Spring bean */ @Bean public App init() { return new App(); } /** * Defines the server query for the list of vineyards */ @Bean @Scope("view") public PagedQuery<Vineyard, Vineyard> vineyards(ServerSession serverSession) throws Exception { PagedQuery<Vineyard, Vineyard> vineyards = new PagedQuery<Vineyard, Vineyard>(serverSession); vineyards.setMethodName("findByFilter"); vineyards.setMaxResults(25); vineyards.setRemoteComponentClass(VineyardRepository.class); vineyards.setElementClass(Vineyard.class); vineyards.setFilterClass(Vineyard.class); return vineyards; } /** * A managed entity that can be used in controllers or views */ @Bean @Scope("view") public ManagedEntity<Vineyard> vineyard(EntityManager entityManager) { return new ManagedEntity<Vineyard>(entityManager); } /** * Client declaration of the data publishing topic */ @Bean(initMethod = "start", destroyMethod = "stop") public DataObserver wineshopTopic(ServerSession serverSession) { return new DataObserver(serverSession); } } /** * Main application */ public static class App { @Inject private Identity identity; @Inject private ContextManager contextManager; @Inject private EntityManager entityManager; @Inject private ServerSession serverSession; public void start(final Stage stage) throws Exception { /** * Attach stage to server session (mostly for busy cursor handling) */ ((JavaFXServerSessionStatus) serverSession.getStatus()).setStage(stage); /** * Attaches a listener to current authentication state to switch between Login and Home screens */ identity.loggedInProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> property, Boolean oldValue, Boolean newValue) { showView(stage, newValue); } }); /** * Checks for current server authentication state at startup */ identity.checkLoggedIn(new SimpleTideResponder<String>() { @Override public void result(TideResultEvent<String> event) { if (event.getResult() == null) showView(stage, false); } @Override public void fault(TideFaultEvent event) { Parent login = showView(stage, false); Label message = (Label) login.lookup("#labelMessage"); message.setText(event.getFault().getFaultDescription()); message.setVisible(true); } }); // Setup conflict handling entityManager.addListener(new DataConflictListener() { @Override public void onConflict(EntityManager entityManager, Conflicts conflicts) { DialogResponse response = Dialogs.showConfirmDialog(stage, "Accept incoming data or keep local changes ?", "Conflict with another user modifications", "Conflict", DialogOptions.YES_NO); if (response == DialogResponse.YES) conflicts.acceptAllServer(); else conflicts.acceptAllClient(); } }); } public void stop() throws Exception { } /** * Displays the requested screen */ private Parent showView(Stage stage, boolean loggedIn) { try { Parent root = (Parent) TideFXMLLoader.load(contextManager.getContext(), loggedIn ? "Home.fxml" : "Login.fxml", loggedIn ? Home.class : Login.class); stage.setScene(new Scene(root)); stage.show(); return root; } catch (Exception e) { log.error("Could not show view", e); } return null; } } private AnnotationConfigApplicationContext applicationContext; /** * Initializes the Spring application context */ @Override public void start(final Stage stage) throws Exception { // Bootstrap Spring with an annotation based context applicationContext = new AnnotationConfigApplicationContext(); // Indicates the packages to scan for Spring beans applicationContext.scan("com.wineshop.client"); applicationContext.scan("com.wineshop.client.services"); applicationContext.refresh(); applicationContext.registerShutdownHook(); applicationContext.start(); // Start the application applicationContext.getBean(App.class).start(stage); } /** * Destroys the Spring application context */ @Override public void stop() throws Exception { // Stop the application applicationContext.getBean(App.class).stop(); // Stop the Spring container applicationContext.stop(); applicationContext.destroy(); } }