Skip to content

Package: JavaFXSpringAnnotationApplication

JavaFXSpringAnnotationApplication

nameinstructionbranchcomplexitylinemethod
JavaFXSpringAnnotationApplication()
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
createApplicationContext()
M: 0 C: 34
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
createSyntheticClassWithAnnotations(Class)
M: 0 C: 44
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
lambda$createApplicationContext$0(int)
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * SteelBlue: DCI User Interfaces
5: * http://tidalwave.it/projects/steelblue
6: *
7: * Copyright (C) 2015 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/steelblue-src
22: * git clone https://github.com/tidalwave-it/steelblue-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.ui.javafx;
27:
28: import jakarta.annotation.Nonnull;
29: import jakarta.inject.Named;
30: import java.util.ArrayList;
31: import java.util.List;
32: import org.springframework.beans.factory.BeanFactory;
33: import org.springframework.context.ConfigurableApplicationContext;
34: import org.springframework.context.annotation.AnnotationConfigApplicationContext;
35: import org.springframework.context.annotation.Bean;
36: import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
37: import it.tidalwave.ui.core.annotation.EnableMessageBus;
38: import it.tidalwave.ui.javafx.impl.AbstractJavaFXSpringApplication;
39: import it.tidalwave.ui.javafx.impl.DefaultJavaFXPanelGroupControl;
40: import net.bytebuddy.ByteBuddy;
41: import net.bytebuddy.description.annotation.AnnotationDescription;
42: import org.slf4j.Logger;
43: import org.slf4j.LoggerFactory;
44: import it.tidalwave.util.PreferencesHandler;
45: import it.tidalwave.messagebus.MessageBus;
46: import it.tidalwave.messagebus.spi.SimpleMessageBus;
47: import lombok.Setter;
48:
49: /***************************************************************************************************************************************************************
50: *
51: * A base class for JavaFX applications with use Spring annotation scanning.
52: *
53: * @author Fabrizio Giudici
54: * @since 1.1-ALPHA-4
55: *
56: **************************************************************************************************************************************************************/
57: public class JavaFXSpringAnnotationApplication extends AbstractJavaFXSpringApplication
58: {
59: /***********************************************************************************************************************************************************
60: * Base bean factory.
61: **********************************************************************************************************************************************************/
62: private static class Beans
63: {
64: @Setter
65: private static AbstractJavaFXSpringApplication application;
66:
67: @Bean
68: public ThreadPoolTaskExecutor javafxBinderExecutor()
69: {
70: return application.getExecutor();
71: }
72:
73: @Bean
74: public PreferencesHandler preferencesHandler()
75: {
76: return PreferencesHandler.getInstance();
77: }
78:
79: @Bean
80: public JavaFXToolBarControl toolBarControl()
81: {
82: return application.getToolBarControl();
83: }
84:
85: @Bean
86: public JavaFXMenuBarControl menuBarControl()
87: {
88: return application.getMenuBarControl();
89: }
90:
91: @Bean
92: public JavaFXPanelGroupControl panelGroupControl (@Nonnull final BeanFactory beanFactory)
93: {
94: return new DefaultJavaFXPanelGroupControl(beanFactory);
95: }
96: }
97:
98: /***********************************************************************************************************************************************************
99: * Auxiliary bean factory for message bus.
100: **********************************************************************************************************************************************************/
101: private static class MessageBusBeans
102: {
103: @Bean(name = MESSAGE_BUS_EXECUTOR_BEAN_NAME)
104: public ThreadPoolTaskExecutor applicationMessageBusExecutor()
105: {
106: final var executor = new ThreadPoolTaskExecutor();
107: executor.setWaitForTasksToCompleteOnShutdown(false);
108: executor.setThreadNamePrefix("messageBus-");
109: executor.setCorePoolSize(10);
110: executor.setMaxPoolSize(10);
111: executor.setQueueCapacity(10);
112: return executor;
113: }
114:
115: @Bean(name = APPLICATION_MESSAGE_BUS_BEAN_NAME)
116: public MessageBus applicationMessageBus (@Named(MESSAGE_BUS_EXECUTOR_BEAN_NAME) final ThreadPoolTaskExecutor executor)
117: {
118: return new SimpleMessageBus(executor);
119: }
120: }
121:
122: public static final String MESSAGE_BUS_EXECUTOR_BEAN_NAME = "applicationMessageBusExecutor";
123:
124: // Don't use Slf4j and its static logger - give Main a chance to initialize things
125: private final Logger log = LoggerFactory.getLogger(JavaFXSpringAnnotationApplication.class);
126:
127: /***********************************************************************************************************************************************************
128: * {@inheritDoc}
129: **********************************************************************************************************************************************************/
130: @Override @Nonnull
131: protected ConfigurableApplicationContext createApplicationContext()
132: {
133: Beans.setApplication(this);
134: // Don't pass getClass() to the ApplicationContext or it will be instantiated — for the second time, since JavaFX launch() already did it.
135: // Instead, create a synthetic class carrying on all its annotations, so the needed features of Spring will be activated.
136: final var componentClasses = new ArrayList<>(List.of(createSyntheticClassWithAnnotations(getClass()), Beans.class));
137:
138:• if (getClass().isAnnotationPresent(EnableMessageBus.class))
139: {
140: log.info("Detected @{}, enabling message bus", EnableMessageBus.class.getSimpleName());
141: componentClasses.add(MessageBusBeans.class);
142: }
143:
144: return new AnnotationConfigApplicationContext(componentClasses.toArray(Class<?>[]::new));
145: }
146:
147: /***********************************************************************************************************************************************************
148: *
149: **********************************************************************************************************************************************************/
150: @Nonnull
151: public static Class<?> createSyntheticClassWithAnnotations (@Nonnull final Class<?> clazz)
152: {
153: var fluent = new ByteBuddy().subclass(Object.class).name(clazz.getPackageName() + ".AnnotationCarrier");
154:
155:• for (final var annotation : clazz.getAnnotations())
156: {
157: fluent = fluent.annotateType(AnnotationDescription.ForLoadedAnnotation.of(annotation));
158: }
159:
160: return fluent.make().load(clazz.getClassLoader()).getLoaded();
161: }
162: }