Git Product home page Git Product logo

jacpfx's Introduction

JacpFX

Event bus, message passing and async execution are concepts, getting more and more popular for server side applications. JacpFX brings this approach to the client, combining JavaFX with an actor-like component model. It is an UI application framework based on JavaFX, supporting developers to structure an application with loosely coupled, reusable components. It frees you from the pitfalls of traditional multi-threaded programming helping you to separate the task execution from UI changes in you client application.

03.12.2015 JacpFX 2.1 final is available in maven.central

JacpFX-2.1 is finally released. Since RC1 (see description below) following issues were fixed:

28.07.2015 JacpFX 2.1-RC1 is available in maven.central

After a longer period without any releases I am pleased to announce JacpFX 2.1-RC1. The JacpFX2.1 release is fixing some issues, adding some minor enhancements and we did a lot of cleanups and optimizations under the hood. If no major issues in RC1 can be found we plan to have a RC2 release in about 4 Weeks before going live. Please take a look at the fixed issues and enhancements, test it and please give feedback on any issue you can find.

Fixed issues:

  • OnShow method not called on application start ( #33 )
    • the lifecycle was fixed so for perspectives now @PostConstruct -> @OnShow (if it’s the current visible) -> @OnHide (if it was hided) -> @Predestroy is valid
  • Let ClassFinder work in Gradle (#32)
    • JacpFX should work with Gradle out-of-the-box
  • Inaccurate exception (#31)
    • Exceptions while loading the FXML should be now more meaningful
  • CSS Error parsing (#28)
  • ToolBar button management fails on two perspectives when second is initially inactive (#11)
  • and more….

Some enhancements:

  • You can now provide your own WorkBenchLayout
    • If you dislike the default Layout implementation with placeholders for ToolBars an so on you can implement your own (more mobile friendly ?)
    • Just implement the WorkbenchDecorator interface and register you implementation in the ApplicationLauncher by overriding the WorkbenchDecorator getWorkbenchDecorator() method. If you have issues with the new default decorator, the old one is still available as DefaultLegacyWorkbenchDecorator.class
  • The JacpContext provides now the fullQualified name
  • Fluent concurrency API provided by JacpContext (#26)
  • Provide SPI for persisting events (#23)
    • implement the MessageLogger interface, create a file called org.jacpfx.api.message.MessageLogger in META-INF/service and add your implementation
org.jacpfx jacpfx.API 2.1-RC1

16.09.2014 JacpFX 2.0.1 is available in maven.central

We released the version 2.0.1 which is mainly a bugfix release. On main issue was fixed when running a JacpFX project on windows with Eclipse or Netbeans, in this case the application start failed. One additional add-on was released with JacpFX 2.0.1, a minimal launcher. So when Spring is not needed in your application you can switch to the minimal launcher and reduce the dependencies.

18.07.2014 JacpFX RC4 is available in maven.central

RC4 release was deployed on maven central. The target for the final release is Aug. 1, so we may release one more RC5 if necessary (hopefully not). We also released a beat for the new project page: http://jacpfx.org . Here you can find the documentation, tutorials and the new blog.

09.07.2014 JacpFX RC3 is available in maven.central

To try out RC3 you can simply use the new (simple) maven archetype:

mvn archetype:generate  -DarchetypeGroupId=org.jacpfx  -DarchetypeArtifactId=JacpFX-simple-quickstart  -DarchetypeVersion=2.0-RC3

10.03.2014 JacpFX RC2 is available in maven.central

We hope that RC3 will be the last RC release before the final JacpFX 2 verion. We still have a lot to do with documentation and the new project page. If you want to test RC2 you can try the JacpFX-vertx demo. Simply start two or more clients, create a server in one of the client-apps and connect the other clients to the created server instance.

09.09.2013 We are currently migrating JacpFX from google code to GitHub!

You can find the old sources [here:] (https://code.google.com/p/jacp/)

09.09.2013 Github is the new repository for JacpFX development

  • JacpFX 2 will run on top of Java8/JavaFX8
  • will have a new an cleaner API
  • migrating from JacpFX 1.x is easy and strait forward

jacpfx's People

Contributors

amoahcp avatar jacpfx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jacpfx's Issues

Fragment to handle respones

So currently a Fragment can send messages to components and callbacks, using context. How it would handle response from such calls? Would it work if fragment implements FXComponent?

Spring Boot support

I use JacpFX. And want to share my implementation, made using Spring Boot.
THANK YOU...

SpringBootLauncher.java

package org.jacpfx.spring.launcher;

import org.jacpfx.api.fragment.Scope;
import org.jacpfx.api.launcher.Launcher;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

/**
* @author created on 07.12.2014 by Javlon Eraliyev 
* 
*/
public class SpringBootLauncher implements Launcher<ApplicationContext> {

    private ConfigurableApplicationContext context;

    @Override
    public ConfigurableApplicationContext getContext() {
        if (context == null) {
            context = SpringApplication.run(ApplicationLauncher.class);
        }
        return context;
    }

    @Override
    public <P> P getBean(Class<P> aClass) {
        return getContext().getBean(aClass);
    }

    @Override
    public <P> P getBean(String s) {
        return (P) getContext().getBean(s);
    }

    @Override
    public <P> P registerAndGetBean(Class<? extends P> type, String id, Scope scope) {
        if (getContext().containsBean(id)) {
            return getBean(id);
        }
        final AutowireCapableBeanFactory factory = getContext().getAutowireCapableBeanFactory();
        final BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
        final GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(type);
        if (scope != null) {
            beanDefinition.setScope(scope.getType());
        }
        beanDefinition.setAutowireCandidate(true);
        registry.registerBeanDefinition(id, beanDefinition);
        factory.autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
        return getBean(id);
    }
}

AFXSpringBootLauncher.java

package org.jacpfx.spring.launcher;

import javafx.stage.Stage;
import org.jacpfx.api.annotations.workbench.Workbench;
import org.jacpfx.api.exceptions.AnnotationNotFoundException;
import org.jacpfx.api.exceptions.AttributeNotFoundException;
import org.jacpfx.api.exceptions.ComponentNotFoundException;
import org.jacpfx.api.fragment.Scope;
import org.jacpfx.api.launcher.Launcher;
import org.jacpfx.rcp.workbench.EmbeddedFXWorkbench;
import org.jacpfx.rcp.workbench.FXWorkbench;
import org.springframework.context.ApplicationContext;
import org.jacpfx.spring.launcher.SpringBootLauncher;

/**
 * JavaFX / Spring application launcher; This abstract class handles reference
 * to spring boot context and contains the JavaFX start method;
 *
 *
 * Example of usage:

 @Configuration
 @ImportResource("classpath:mySpringApplicationContext.xml")
 public class ApplicationLauncher extends AFXSpringBootLauncher {

     public static void main(String[] args) {
        Application.launch(args);
     }

     @Override
     protected Class<? extends FXWorkbench> getWorkbenchClass() {
        return MyJacpFXWorkbench.class;
     }

     @Override
     protected String[] getBasePackages() {
        return new String[]{"my.company"};
     }

     @Override
     public void postInit(Stage stage) {
         mainStage = stage;
         Scene scene = stage.getScene();
         // add style sheet
         scene.getStylesheets().addAll(
            ApplicationLauncher.class.getResource("/myFolder/myStyle.css").toExternalForm()
         );
     }
 }

 *
 *
 * @author created on 07.12.2014 by Javlon Eraliyev
 */
public abstract class AFXSpringBootLauncher extends ASpringLauncher {

    @SuppressWarnings("unchecked")
    @Override
    public void start(Stage stage) throws Exception {
        initExceptionHandler();
        scanPackegesAndInitRegestry();
        final Launcher<ApplicationContext> launcher = new SpringBootLauncher();
        final Class<? extends FXWorkbench> workbenchHandler = getWorkbenchClass();
        if (workbenchHandler == null) throw new ComponentNotFoundException("no FXWorkbench class defined");
        initWorkbench(stage, launcher, workbenchHandler);
    }

    private void initWorkbench(final Stage stage, final Launcher<ApplicationContext> launcher, final Class<? extends FXWorkbench> workbenchHandler) {
        if (workbenchHandler.isAnnotationPresent(Workbench.class)) {
            this.workbench = createWorkbench(launcher, workbenchHandler);
            workbench.init(launcher, stage);
            postInit(stage);
        } else {
            throw new AnnotationNotFoundException("no @Workbench annotation found on class");
        }
    }

    private EmbeddedFXWorkbench createWorkbench(final Launcher<ApplicationContext> launcher, final Class<? extends FXWorkbench> workbenchHandler) {
        final Workbench annotation = workbenchHandler.getAnnotation(Workbench.class);
        final String id = annotation.id();
        if (id.isEmpty()) throw new AttributeNotFoundException("no workbench id found for: " + workbenchHandler);
        final FXWorkbench handler = launcher.registerAndGetBean(workbenchHandler, id, Scope.SINGLETON);
        return new EmbeddedFXWorkbench(handler);
    }

}

Dependency in pom.xml

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring.boot.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>log4j-over-slf4j</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
</dependency>

ResourceBundle not injectable into Callback Component?

Hi Andy,

It seems a resource bundle should be injectable into a callback component based on the @component annotation allowing the resource bundle location to be set. I was getting a null pointer exception for a resource bundle in a callback component.

@component(id = "MyComponentId",
name = "My Component",
resourceBundleLocation = "bundles.languageBundle")

I looked through the code and am not certain, but should the method handling the callback component annotation save the resource bundle location in the component like @view and @DeclarativeView so it can later be retrieved and injected?

Below is a portion from PerspectiveUtil.java. The callback component method doesn't save the resource bundle like the view component method.

/**
* Handle a callback component metadata.
* @param component, The target component.
* @param callbackAnnotation, The callback annotation.
*/
private static void handleCallbackAnnotation(final SubComponent<EventHandler, Event, Object> component, final Component callbackAnnotation) {
handleBaseAttributes(component, callbackAnnotation.id(), callbackAnnotation.active());
}

/**
 * Set all metadata from @View and @Component annotation to the target component.
 * @param component, The target component.
 * @param viewComponent, The @View annotation.
 */
private static void handleViewComponentAnnotation(final SubComponent<EventHandler<Event>, Event, Object> component,final View viewComponent) {
    handleBaseAttributes(component, viewComponent.id(), viewComponent.active());
    setInitialLayoutTarget(component, viewComponent.initialTargetLayoutId());
    setLocale(component, viewComponent.localeID());
    setResourceBundleLocation(component, viewComponent.resourceBundleLocation());
    log("register component with annotations : " + viewComponent.id());
}

Thanks

Santiago

Unable to run simple project from archetype using gradle

Hey guys,

I've recently started playing with your framework and as a fan of gradle, I converted maven project into gradle one. After running main class I've got 5-6 ClassNotFoundException.
The problem was with ClassFinder:170. You assumed, that all class-files with package-dirs are in "classes"-folder. But gradle keeps file in a bit different way:

MacBook-Pro-Konstantin:perspective konstantinpasko$ ls
PerspectiveOne.class    PerspectiveTwo.class
MacBook-Pro-Konstantin:perspective konstantinpasko$ pwd
/Users/konstantinpasko/test-jacpfx/build/classes/production/test-jacpfx/com/gui/perspective

I've fixed in this pull-request (#20). I hope it doesn't break anything else.

Regards,
Konstantin.

Not all Nodes can be used as targets

Hi Andy,

For example, if I use ScrollPane as target in perspective component's ui is ignored and not injected into the target. So far GridPane is working fine for me as target.

thanks,

Alex.

Enable 3D support

Hi Andy,

is it possible to enabled 3d support for the scene? When creating Scene 4rth parameter (depthBuffer) should be true.
Method completeLayout() in AFXWorkbench inits Scene, but how to override or configure it?

thanks,

Alex.

Preserve view state

Currently JacpFX creates always the initial state of you perspective/components. Make it possible to save the state and to revert to the last view state.

Component "postHandle" Method Does Not Receive Message The 2nd Time Sent

Hi,

I ran into an issue with 2.1-RC4 where a component is sending a message within the same component from the handle method. The first time the component's postHandle method received the message, but the second time the component sent the same message the postHandle no longer received the message. I have zipped up sample, but I'm not able to attach it to this issue. I can provide the sample to you by whatever means you'd like.

Reproduction Steps:

  1. Run sample.
  2. Press "Go To Component TWO" button.
  3. See component two is displayed.
  4. Press "Go To Component ONE" button.
  5. See component one is displayed again like the first time in step #1.
  6. Press "Go To Component TWO" button again and notice component two is not displayed like in step #3.
  7. The message sent by the handle method of component two is never received by postHandle.

Thanks

Santiago

replace "handle" & "postHandle" methods by typed message annotations

components and perspectives currently must implement a "handle" method and in some cases a "postHandle" method. You must manually check the type for each message, which can create some nasty code.
Idea: Instead of implementing the methods, allow typed annotations like:

"@HandleAsync(type=MyMessage.class) "
Node onAsyncMyMessage(MyMessage message);
or
"@HandleAsync(type=MyMessage.class) "
Node onAsyncMyMessage(MyMessage message);

and

"@handle(type=MyMessage.class) "
Node onMyMessage(MyMessage message);
or
"@handle(type=MyMessage.class) "
Node onMyMessage(Message<Event, MyMessage> message);

Risk: like "handle" and "postHandle" the annotation driven way must keep the order of execution which means, that async execution must always be done before sync execution.

Pro: Should be possible to keep current interfaces and use them to implement the annotation driven way, also backwards compatibility should be given.

CSS Error parsing

警告: CSS Error parsing jar:file:/C:/Users/xxx/.m2/repository/org/jacpfx/jacpfx.JavaFX/2.0.2/jacpfx.JavaFX-2.0.2.jar!/styles/jacp-styles.css: Expected LBRACE at [1,9]

@charset "ISO-8859-1";

java1.8_45

Support TabPane as TargetLayoutComponent

I'm would like to use TabPane as target (initialTargetLayoutId) for Views to mimic the editor area of an IDE, but a TabPane takes Tab instances, which are not subclasses of Node, so currently that doesn't seem possible.

I ended up creating a an FXComponent that wraps Node elements in a Tab before adding them to the TabPane, but for this I have to instantiate a Fragment or just unmanaged JavaFX components, which means they cannot be message targets. I would really like the elements of my TabPane to be Views that I can dynamically inject into my TabPane.

Can you see a possible solution for this, or would it be possible to implement special support for TabPane?

Current use case: A search TextField in the toolbar fires a message to a CustomerService component that fetches a list of customers, then instantiates a CustomerList View and adds it as a Tab to the TabPane editor area.

Sorry if I missed something and this doesn't make sense at all, it's my first day with JacpFX. Really enjoy the concepts though :)

Handle @View without targetLayout

a.) @view has an invalid initialTargetLayoutId AND a return value... EXCEPTION
b.) @view has an empty initialTargetLayoutId AND a return value... EXCEPTION
c.) @view has an empty initialTargetLayoutId AND NO return value.. OK
d.) @view has a VALID initialTargetLayoutId AND NO return value ... remove old one OK

@PostConstruct lifecycle

Check that @PostConstruct in Components is always executed in Worker Thread. To avoid problems with context methods ensure that all UI methods in context object are surrounded by "invokeLater".

Let ClassFinder work in Gradle

gradle compile Class to "projectRoot/build/classes/main", that ClassFinder can't find Perspectives and Components in "classes".
I rewrite ClassFinder#exctractClasses.

private List<Class> exctractClasses(final String packageDir, List<String> files) {
    return files.stream()
            .map(Paths::get)
            .map(path -> binDirs.stream()        // find the right classpath of file
                    .filter(path::startsWith)
                    .findFirst()
                    .map(p -> p.relativize(path)))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .filter(path -> path.startsWith(packageDir))
            .map(path -> path.toString().replace(File.separator, CLASS_DOT))
            .map(className -> className.substring(0, className.lastIndexOf(CLASS_FILE)))
            .filter(classFile -> !classFile.contains(CLASS_DOLLAR))
            .map(this::loadClass)
            .filter(clazz -> clazz != null)
            .collect(Collectors.toList());
}

I don't know if it can work in maven.
This is my sample project: http://git.oschina.net/ellipse/JacpFXSample

Possible issue with Toolbar Buttons

Possible issue with Toolbar Buttons while regression test... PerspectiveHandlerImple line 255. The code is currently working but when small change can cause unexpected behavior! Find out what is going on ...

I can not use onAction="#foo" in perspective- and component- FXML, BUG or FEATURE?

Hi@ all,
if i tried to load a FXML structure in a perspective or a component, i got this error.

java.util.MissingResourceException: fxml file not found --  place in resource folder and reference    like this: viewLocation = "/myUIFile.fxml"

The FXML file include parts like this: <Button onAction="#save" text="Save" />
If i deleted this part it works!

Is this a bug, a feature or what i am doing wrong?

Thank you for response!

Greetings Meho

How can I deal with Accelerators?

I want to bind my button with shortcut, e.g. F2, CTRL+2...
Scene always comes null in method postHandle(Node, Message).
I know that I can get main scene and set accelerators but it triggers in all perspectives.

How can I set accelerators only for one perspective?
Is there any trick?

Some questions, impressions and possible improvements

First of all: Nice project! It worked just out of the box with Spring.

Now my questions and suggestions:

1.:
Why are there workbench, perspective, components and fragments? It's clear to me that you want to define some abstraction for windows, layout, etc.
But: Wouldn't it be much simpler if there were only components? Each component can have 0-n child components. (and all the other stuff like viewLocation and scope (which is by default singleton) ).

2.:
Why is the components field inside the Perspective annotation mandatory? The documentation says, that 0-n components can be used. (and it works when using 0 components inside a perspective)

3.:
Why do I have to provide the full package path to my fxml files? In my opinion the fxml file belongs to the component and most often you don't reuse the fxml file. Though I'd like to simply use viewLocation="foo.fxml" if the fxml file is in the same package as the component. When the fxml file is somewhere else you can still use /path/to/file/foo.fxml (beginning with /). You could simply use getClass().getPackage().getName().

4.:
Why are there 2 view annotations? View and DeclarativeView. Get rid of the DeclarativeView and just look if viewLocation is null / empty.

Maybe version 2.1 or 2.2 could get rid of some these issues :)

How to register the center of BordPane as an target layout?

Hi again :-),

if i write this:

perspectiveLayout.registerTargetLayoutComponent(BasicConfig.P_CONTACT, contentArea.getCenter());

I got this:

no targetLayout for layoutID: P_Contact found

P_Contact is the ID of BasicConfig.P_CONTACT.
contentArea is the name of my BorderPane in FXML and i injected it like this:

@FXML
private BorderPane contentArea;

Is it possible to register a center of BorderPane?

THX!
Greetings Meho

Add button to toolbar in component does not work

Adding a button without explicit id does fail, no button appears in toolbar.
JACPToolBar toolbar = layout.getRegisteredToolBar(ToolbarPosition.NORTH);
toolbar.addOnEnd(new Button("dfsdfsd"));

Adding a button with explicit id works.
JACPToolBar toolbar = layout.getRegisteredToolBar(ToolbarPosition.NORTH);
toolbar.addOnEnd("xyz",new Button("dfsdfsd"));

Empty perspective when switch to new Perspective

Two Perspectives (both active), both with a SplitPane as Root and GridPanes as targets. Two Components, returning a Label. Both Components assigned to Perspective one and two... when switching from P1 to P2 no content is visible, also all Nodes are available. When P2 is initially deactivated, everything works ok.

some annotation conflict with java build-in package

Hi,
I find some annotations used in jacpfx such as @PostConstruct and @PreDestory is in the package org.jacpfx.api.annotations, but in the package javax.annotation it also contain the @PostConstruct annotation. So I want to know what's the difference between these two annotations.
I want to integrate jacpfx into my springboot framework project. So I want to know how to operate these same name but in different package annotations.
In addition,I find a issue about springboot titled "Spring Boot support" , It's ok?
Thank you!

Fluent concurrency API provided by JacpContext

Provide a CompletableFuture like API to execute tasks and GUI updates. "Abstract" CompletableFuture and reduce API complexity.
My current test implementation is like that:

context.getAsyncHandler().
supplyOnExecutorThread(() -> service.getAllValues()).
functionOnExecutorThread((values) -> values.stream().map(val->new Button(val.toString())).collect(Collectors.toList())).
consumeOnFXThread((buttonList)->node.getChildren().addAll(buttonList)).
.execute();

define a modules system for JacpFX

JacpFX allows you to create several packages containing Perspectives and Components but there is no defined structure to create packages.
What should be able:

  • define module with 1 perspective and many components
  • define own classloader per module
  • allow reload module
  • allow update module

Use of system class loader in ClassFinder

Hello !

First of all, a big thank for your work and framework that is very useful for us!

I have recently tried to plug Load Time Weaving (LTW) in our application using Spring and AspectJ and I faced an issue: my aspect was not weaved.

It was due to the fact that the ClassFinder loads classes in base packages using the system class loader (see org.jacpfx.rcp.util.ClassFinder.loadClass(String)). Indeed, to be weaved, the class must be loaded thanks to the Spring org.springframework.core.OverridingClassLoader which does not always delegate to the parent class loader.

So, I think that

return ClassLoader.getSystemClassLoader().loadClass(file);

should be replaced by

return this.getClass().getClassLoader().loadClass(file);

Current workaround consists in locating the aspect outside of the JacpFX base packages.

Many thanks in advance,
Cheers,
Jean.

ResourceBundle injection in FXPerspective

Hi Andy,

It seems that resource bundle is never injected the first time a FXPerspective is accessed.

Indeed, in case of FXPerspective, resource bundle injection is done at line 253 of org.jacpfx.rcp.handler.PerspectiveHandlerImpl.initComponent(Message<Event, Object>, Perspective<Node, EventHandler<Event>, Event, Object>) (calling org.jacpfx.rcp.util.FXUtil.performResourceInjection(Injectable, JacpContext<EventHandler<Event>, Object>) which will use the resource bundle associated to the context) while the association of the resource bundle to the context will only be done at line 255 of org.jacpfx.rcp.handler.PerspectiveHandlerImpl.initComponent(Message<Event, Object>, Perspective<Node, EventHandler<Event>, Event, Object>) by the call to org.jacpfx.rcp.handler.PerspectiveHandlerImpl.handlePerspectiveInitialization(Perspective<Node, EventHandler<Event>, Event, Object>).

Current workaround consists in getting the resource bundle from the context directly or in using the resource bundle provided as argument of the method annotated by @PostConstruct.

Note that everything works well for managed fragments.

Thanks in advance!

Cheers,
Jean.

Thread leaks and memory leaks when deactivating/activating components

When components are deactivated and activated again I can observe the "old" EmbeddedFXComponentWorker threads still active although they shouldn't be. The problem doesn't appear every time I debug the code. It seems to depend on where I put breakpoints and delay the execution. See thread "ControlView" in the attached "jvisualvm" screenshot:

threads

Since these threads reference EmbeddedFXComponents which in turn reference UI components there are memory leaks as well.

The problem seems to be that when lock.unlock() in WorkerUtil:101 interrupts getNextIncomingMessage() in EmbeddedFXComponentWorker:93 we immediately end up calling handleComponentExecution() again in line 82. (The line numbers correspond to the sources as they appear in version 2.1.)

There seems to be a t.interrupt() missing where the InterruptedException is caught (line 112):

        } catch (InterruptedException e) {
            t.interrupt();
        } catch (Exception e) {

The same probably holds for EmbeddedCallbackComponentWorker (line 92). Maybe check other occurrences where InterruptedException is caught as well. I've found a couple of occurrences where InterruptedException is neither propagated nor the interrupted flag set.

The problems seems to exist in the current master version (EmbeddedFXComponent:130) as well.

From what I gathered there is no context.setActive() to activate/deactive components anymore. Unfortunately I make heavy use of activating/deactivating components in my application.

Inaccurate exception

org.jacpfx.rcp.util.FXUtil line 310

fxmlLoader throw an exception: javafx.fxml.LoadException: Resource "hello" not found.
/E:/devel/JacpFXSample/build/resources/main/fxml/ComponentRight.fxml:10
It means the fxml is exists, and some resource defined in fxml not found.

FXUtil report "fxml file not found ...", it is misleading.

@OnShow method not called on application start

@onshow method of default Perspective is not called on application start, and @OnHide method is not called on shutdown application.

五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.perspective.PerspectiveOne onStartPerspective
信息: on PostConstruct of PerspectiveOne
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.callback.StatefulCallback onPostConstructComponent
信息: run on start of StatefulCallback
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.perspective.PerspectiveTwo onStartPerspective
信息: on PostConstruct of PerspectiveTwo
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.perspective.PerspectiveTwo handlePerspective
信息: message to PerspectiveTwo:org.jacpfx.rcp.message.MessageImpl@59318c5c
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.callback.StatelessCallback onPostConstructComponent
信息: run on start of StatelessCallback
五月 21, 2015 11:54:39 下午 org.jacpfx.rcp.workbench.AFXWorkbench init
信息: INIT
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.component.ComponentLeftTop onPostConstructComponent
信息: run on start of ComponentLeft
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.component.ComponentLeftTop onPostConstructComponent
信息: run on start of ComponentLeft
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.component.ComponentRight onPostConstructComponent
信息: run on start of ComponentRight
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.component.ComponentRight onPostConstructComponent
信息: run on start of ComponentRight
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.component.ComponentLeft onPostConstructComponent
信息: run on start of ComponentLeft
五月 21, 2015 11:54:39 下午 org.jacpfx.jfxMPD.component.ComponentLeft onPostConstructComponent
信息: run on start of ComponentLeft
p1.button pressed
on ##hide## of PerspectiveTwo
on ##show## of PerspectiveOne
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[ComponentDelegator,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[MessageDelegatorImpl,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.delegator.ComponentDelegator run
信息: queue in ComponentDelegator interrupted
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.delegator.MessageDelegatorImpl run
信息: queue in ComponentDelegator interrupted
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[MessageCoordinator,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[MessageCoordinator,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.coordinator.ACoordinator run
信息: queue in ACoordinator interrupted
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[MessageCoordinator,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.coordinator.ACoordinator run
信息: queue in ACoordinator interrupted
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.coordinator.ACoordinator run
信息: queue in ACoordinator interrupted
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[statefulCallback,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[SimpleView,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[SimpleView,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[SimpleView,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[SimpleView,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[SimpleView,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.rcp.util.ShutdownThreadsHandler shutdowAll
信息: shutdown thread: Thread[SimpleView,5,main]
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.component.ComponentLeft onPreDestroyComponent
信息: run on tear down of ComponentLeft
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.component.ComponentRight onPreDestroyComponent
信息: run on tear down of ComponentRight
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.component.ComponentLeftTop onPreDestroyComponent
信息: run on tear down of ComponentLeft
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.callback.StatefulCallback onPreDestroyComponent
信息: run on tear down of StatefulCallback
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.perspective.PerspectiveOne onTearDownPerspective
信息: on PreDestroy of PerspectiveOne
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.component.ComponentLeft onPreDestroyComponent
信息: run on tear down of ComponentLeft
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.component.ComponentRight onPreDestroyComponent
信息: run on tear down of ComponentRight
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.component.ComponentLeftTop onPreDestroyComponent
信息: run on tear down of ComponentLeft
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.callback.StatelessCallback onPreDestroyComponent
信息: run on tear down of StatelessCallback
五月 21, 2015 11:54:50 下午 org.jacpfx.jfxMPD.perspective.PerspectiveTwo onTearDownPerspective
信息: on PreDestroy of PerspectiveTwo

ClassFinder.extractClasses Expects "classes" as part of path.

Hi,

Nice work on the framework!

I've been exploring the framework in the Intellij IDE and found I was not able to run my project in the IDE with the default Intellij class output path.

It appears the ClassFinder extractClasses method always expects a "classes" part of the file path, but that's the not the default that an Intellij IDE gives for a JavaFX project. I'm able to change it in my project to make it work, but I thought I'd report what I found.

In particular the following lines from extractClasses will return an incorrect substring if classes is not found in the file path:

    String seperator = "classes".concat(File.separator);
    return (List)files.parallelStream().map((dir) -> {
        return dir.substring(dir.lastIndexOf(seperator) + 8, dir.length());
    }).filter((classDir) -> {
   ...

Thanks

Santiago

UI FXComponent doesn't recognize the controls in fxml file, imported using fx:include

Hi Andy,

FXComponent view doesn't initialize the controls in the fxml file which are included using tag fx:include. In the below example, the control with id apperror is null in the instantiated FXComponent

for example,

contents of main.fxml

<BorderPane prefHeight="211.0" prefWidth="225.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <center>

    </center>
   <bottom>
        <fx:include source="footer.fxml" />
    </bottom>
</BorderPane>

contents of footer.xml

<HBox alignment="CENTER_RIGHT" maxHeight="-Infinity" >
    <children>
      <Button fx:id="apperror" mnemonicParsing="false" text="" style="-fx-background-color: white;"/>
     </children>
    <padding>
        <Insets bottom="12.0" left="12.0" right="12.0" top="12.0" />
    </padding>
</HBox>

Make @View.name() default to @View.id()

In all my @view components I find myself setting the same value for the id and name attributes. It would be nice if name could default to the id attribute value if not specified.

I'm not completely sure why I need to specify name at all, I have had no use for it so far :)

Provide SPI for persisting events

Hi Andy,

I think it would be nice to provide an SPI to enable persisting all the events generated by the user interaction with the application. Which can be useful in finding\analyzing the user behavior.

Something like durable message queue?

Thanks

ThrowableWrapper is not thread-safe

ThrowableWrapper is not thread-safe, because it does not publish its invariants safely. You want to make its public field final or volatile (if writing is necessary)

Also, while you are at it, it might be a good idea to introduce a equals, hashCode and toString method as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.