JavaFX FXML Parameter passing from Controller A to B and back - parameter-passing

I want to create a controller based JavaFX GUI consisting of multiple controllers.
The task I can't accomplish is to pass parameters from one Scene to another AND back.
Or in other words:
The MainController loads SubController's fxml, passes an object to SubController, switches the scene. There shall not be two open windows.
After it's work is done, the SubController shall then switch the scene back to the MainController and pass some object back.
This is where I fail.
This question is very similar to this one but still unanswered. Passing Parameters JavaFX FXML
It was also mentioned in the comments:
"This work when you pass parameter from first controller to second but how to pass parameter from second to first controller,i mean after first.fxml was loaded.
– Xlint Xms Sep 18 '17 at 23:15"
I used the first approach in the top answer of that thread.
Does anyone have a clue how to achieve this without external libs?

There are numerous ways to do this.
Here is one solution, which passes a Consumer to another controller. The other controller can invoke the consumer to accept the result once it has completed its work. The sample is based on the example code from an answer to the question that you linked.
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(
(Pane) loader.load()
)
);
Consumer<CustomerInteractionResult> onComplete = result -> {
// update main screen based upon result.
};
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer, onComplete);
stage.show();
return stage;
}
...
class CustomerDialogController() {
#FXML private Label customerName;
private Consumer<CustomerInteractionResult> onComplete
void initialize() {}
void initData(Customer customer, Consumer<CustomerInteractionResult> onComplete) {
customerName.setText(customer.getName());
this.onComplete = onComplete;
}
#FXML
void onSomeInteractionLikeCloseDialog(ActionEvent event) {
onComplete.accept(new CustomerInteractionResult(someDataGatheredByDialog));
}
}
Another way to do this is to add a result property to the controller of the dialog screen and interested invokers could listen to or retrieve the result property. A result property is how the in-built JavaFX dialogs work, so you would be essentially imitating some of that functionality.
If you have a lot of this passing back and forth stuff going on, a shared dependency injection model based on something like Gluon Ignite, might assist you.

I've used AfterBurner.fx for dependency injection, which is very slick and powerful as long as you follow the conventions. It's not necessarily an external lib if you just copy the 3 classes into your structure. Although you do need the javax Inject jar, so I guess it is an eternal reference.
Alternately, if you have a central "screen" from which most of your application branches out you could use property binding probably within a singleton pattern. There are some good articles on using singleton in JavaFX, like this one. I did that for a small application that works really great, but defining all of those bindings can get out of hand if there are a lot of properties.

To pass data back, the best approach is probably to fire custom Events, which the parent controller subscribes to with Node::addEventHandler. See How to emit and handle custom events? for context.
In complex cases when the two controllers have no reference to each other, a Event Bus as #jewelsea mentioned is the superior option.
For overall architecture, this Reddit comment provides some good detail: https://www.reddit.com/r/java/comments/7c4vhv/are_there_any_canonical_javafx_design_patterns/dpnsedh/

Related

Not able to fetch data from array in JSF [duplicate]

I've a data table as below:
<h:dataTable value="#{bean.items}" var="item">
I'd like to populate it with a collection from the database obtained from a service method so that it is immediately presented when the page is opened during an initial (GET) request. When should I call the service method? And why?
Call it before page is loaded. But how?
Call it during page load. How?
Call it in the getter method. But it is called multiple times.
Something else?
Do it in bean's #PostConstruct method.
#ManagedBean
#RequestScoped
public class Bean {
private List<Item> items;
#EJB
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public List<Item> getItems() {
return items;
}
}
And let the value reference the property (not method!).
<h:dataTable value="#{bean.items}" var="item">
In the #PostConstruct you have the advantage that it's executed after construction and dependency injection. So in case that you're using an EJB to do the DB interaction task, a #PostConstruct would definitely be the right place as injected dependencies would not be available inside a normal constructor yet. Moreover, when using a bean management framework which uses proxies, such as CDI #Named, the constructor may or may not be called the way you expect. It may be called multiple times during inspecting the class, generating the proxy, and/or creating the proxy.
At least do not perform the DB interaction job in the getter, unless it's lazy loading and you really can't do anything else. Namely, it would be invoked during every iteration round. Calling the service method during every iteration round is plain inefficient and may end up in "weird" side effects during presentation and postbacks, such as old values from DB seemingly still sticking around in the model instead of new submitted values.
If you rely on GET request parameters, then use <f:viewParam> and <f:viewAction> instead. See also Creating master-detail pages for entities, how to link them and which bean scope to choose.
If you want to preserve the model (the items property) across postbacks on the same view (e.g. CRUD table/dialog), then make the bean #ViewScoped, else the model won't be in sync with the view when the same model is concurrently edited elsewhere. See also Creating master-detail table and dialog, how to reuse same dialog for create and edit.
If you utilize JPA's #Version feature on the model, then you can catch OptimisticLockException to deal with it and show a message like "The data has been edited by someone else, please refresh/review if the desired changes are as intended". See also Letting the presentation layer (JSF) handle business exceptions from service layer (EJB).
See also:
Why JSF calls getters multiple times
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
JSF Controller, Service and DAO

primefaces datatable query twice [duplicate]

I've a data table as below:
<h:dataTable value="#{bean.items}" var="item">
I'd like to populate it with a collection from the database obtained from a service method so that it is immediately presented when the page is opened during an initial (GET) request. When should I call the service method? And why?
Call it before page is loaded. But how?
Call it during page load. How?
Call it in the getter method. But it is called multiple times.
Something else?
Do it in bean's #PostConstruct method.
#ManagedBean
#RequestScoped
public class Bean {
private List<Item> items;
#EJB
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public List<Item> getItems() {
return items;
}
}
And let the value reference the property (not method!).
<h:dataTable value="#{bean.items}" var="item">
In the #PostConstruct you have the advantage that it's executed after construction and dependency injection. So in case that you're using an EJB to do the DB interaction task, a #PostConstruct would definitely be the right place as injected dependencies would not be available inside a normal constructor yet. Moreover, when using a bean management framework which uses proxies, such as CDI #Named, the constructor may or may not be called the way you expect. It may be called multiple times during inspecting the class, generating the proxy, and/or creating the proxy.
At least do not perform the DB interaction job in the getter, unless it's lazy loading and you really can't do anything else. Namely, it would be invoked during every iteration round. Calling the service method during every iteration round is plain inefficient and may end up in "weird" side effects during presentation and postbacks, such as old values from DB seemingly still sticking around in the model instead of new submitted values.
If you rely on GET request parameters, then use <f:viewParam> and <f:viewAction> instead. See also Creating master-detail pages for entities, how to link them and which bean scope to choose.
If you want to preserve the model (the items property) across postbacks on the same view (e.g. CRUD table/dialog), then make the bean #ViewScoped, else the model won't be in sync with the view when the same model is concurrently edited elsewhere. See also Creating master-detail table and dialog, how to reuse same dialog for create and edit.
If you utilize JPA's #Version feature on the model, then you can catch OptimisticLockException to deal with it and show a message like "The data has been edited by someone else, please refresh/review if the desired changes are as intended". See also Letting the presentation layer (JSF) handle business exceptions from service layer (EJB).
See also:
Why JSF calls getters multiple times
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
JSF Controller, Service and DAO

AS3: Create static variables in registry from external list

I have an application which will be using large numbers of assets. In order to better handle that I chose to use a registry to hold all the assets so they are accessible across the entire application:
package
{
public class SpriteRegistry
{
public static var SPRITENAME = "link to image file";
public function SpriteRegistry()
{
}
}
}
What I would like to do is create an XML document and list off the file name and link so that when the application starts, this registry creates its variables which are freely accessible from that list without me needing to hard code any content directly into it.
Specifically what I need to know is how to get the "public static" effect or how to get an equivalent effect for variables that I CAN dynamically produce.
More info:
I am using a function that loads a sprite texture into a sprite object based on a string variable called mouseAttribute:
loadGraphic(SpriteRegistry[currentAttribute+"Texture"]);
Basically it's like a painting program but for a level editor for a video game.
The problem is that I'm eventually going to have 100+ sprites that I need to application to load and then I need the loadGraphic function to still be able to point effectively to the target sprite.
The library I'm using also needs me to embed the source into a class before I can pull it into the sprite object:
[Embed(source = "/Images/GridTile.png")]
public static var gridTileTexture:Class;
The reason I'm trying to avoid an array is because it means that I will have to search through an array of 100+ objects to find one sprite every time I click a single grid on the editor. That is going to chug.
It's very simple - just use a static function, which will return the XML. So you will need to load the XML file somehow (you decide where, but your registry class should have reference to it). Something similar to this:
private static var _xml:XML;
public static function initialize(xml:XML):void {
_xml = xml;
}
public static function getXML():XML {
return _xml;
}
So you will use it like that:
SpriteRegistry.initialize(loadedXML); // done only once when you initialize your app
trace(SpriteRegistry.getXML().someValue); // someValue is directly from the XML
It's a common used strategy and most of the times you would have something like an app initializer - something to load and instantiate all the things, then pass them to some registries that keep them stored for faster and global usage.
Edit:
After reading your further comments, I can't see any big change - everything would be ok with this resolution.
If you are worried about the 'need to search through array' - just do it as an object! This way you will be able to directly access the proper one using a key exactly like you pointed:
private static var _registry:Object;
public static function initialize(xml:XML):void {
// loop through xml and insert items
_registry[key] = resource;
}
public static function getResource(id):Object {
return _registry[id];
}
This way you can use it like:
SpriteRegistry.getResource(currentAttribute+"Texture");
My personal opinion is that you should avoid statics wherever possible. Instead, you should just create a single instance and provide it through dependency injection where needed.
If you were to go with that approach, you could do something like:
public function getSprite(spriteName:String):Class{
return this[spriteName];
}
or
public function getSprite(spriteName:String):Class{
return yourDictionaryOrObject[spriteName];//I'd implement it this way
}
Otherwise you could go with something like:
public static function getSprite(spriteName):Class{
return ThisHonkingBigUnnchangeableClassname[spriteName];
}
What I would not do is create a Dictionary in a static-only Class, because you're almost inevitably going to wind up with global mutable state.
Discussion, per request
Why would you want to create an instance and pass it, rather than hard-code a reference to a specific Class? A lot of the answers are covered in the global mutable state link above, but here are some that are specific to this kind of problem:
Flexibility. Say you build everything with the idea that you'd only have one set of resources being used in parallel, then you discover you need more than one--for example you might need one for color blind users, or multiple languages, or thumbnails vs. full-sized. If you hard-code to a static, then you'll have to go in every place that was hard-coded and make some sort of change to use a different set, whereas if you use DI, you just supply a different instance loaded with different resources, and done.
Testability. This is actually covered in the link, but I think it bears pulling out. If you want to run a quick test on something that needs a resource, you have to have that static "thing" and you can't change anything about it. It then becomes very difficult to know if the thing you're actually testing is working or if it just appears to be working based on the current implementation of the "thing."
Resource use: everything about an all-static Class exists from the time the swf loads to the time it unloads. Instances only exist from when you instantiate them until they are garbage collected. This can be especially important with resource files that contain embedded assets.
I think the important thing about Frameworks is to realize how they work. The major ones used in ActionScript work the same way, which is they have a central event dispatcher (event bus) that anything loaded to the framework can get a reference to by declaring an interest in it by asking for it to be injected. Additionally, they watch the stage for an event that says that something has been added (in RL it's ADDED_TO_STAGE, whereas in Mate it's the Flex event CREATION_COMPLETE). Once you understand these principles, you can actually apply them yourself with a very light hand without necessarily needing everything that comes along with a framework.
TL;DR
I usually try to avoid answering questions that weren't asked, but in this case I think it would be helpful to discuss an entirely different approach to this problem. At root, the solution comes down not to injecting an entire resource instance, but instead just injecting the resource that's needed.
I don't know what the OP's code is like, but this solution should be general enough that it would work to pass named BitmapDatas to anything that implements our Interface that is capable of dispatching against whatever IEventDispatcher we set as the eventBus (this could be the stage, a particular DisplayObject, or an EventDispatcher that is created just for the purpose.
Note that this code is strikingly similar to code I have in production ;).
public class ResourceManager {
//this can be loaded dynamically, or you can create subclasses that fill the registry
//with embedded Classes in the constructor
protected var registry:Dictionary = new Dictionary();
protected var _eventBus:IeventDispatcher;
public function registerResource(resourceName:String, resourceClass:Class):void {
var bitmap:BitmapData = new resourceClass as BitmapData;
if (resourceClass) {
registry[resourceName] = bitmap;
} else {
trace('Class didn\'t make a BitmapData');
}
}
public function getResource(resourceName:String):BitmapData {
var resource:BitmapData = registry[resourceName];
if (!resource) trace('there was no resource registered for', resourceName);
}
public function get eventBus():IEventDispatcher {
return _eventBus;
}
public function set eventBus(value:IEventDispatcher):void {
if (value != _eventBus){
if (_eventBus) {
_eventBus.removeEventListener(YourCustomEvent.GET_RESOURCE, provideResource);
}
_eventBus = value;
if (_eventBus) {
_eventBus.addEventListener(YourCustomEvent.GET_RESOURCE, provideResource);
}
}
}
protected function provideResource(e:YourCustomEvent):void {
var client:IBitmapResourceClient = e.target as IBitmapResourceClient;
if (client) {
client.resource = getResource(e.resourceName);//your custom event has a resourceName property that you populated when you dispatched the event.
}
}
}
Note that I didn't provide the Interface or the custom event or an example implementation of the Interface due to the fact I am on my lunch break, but if anyone needs that to understand the code please post back and I'll fill that in.

How to call a remoteObject method that is outside of my TitleWindow component on Flex?

I have a TitleWindow component. It allows me to save some data provided through 3 TextInput.
That data "fills" a DropDownList which is in another TitleWindow component, not inside the original one.
How can I call the remoteObject method that fills (or refresh) my DropDownList?
Any ideas will be appreciated!
You can simply use a Singleton as a model if you'd like, this will allow you to share data, but beware keep data only that needs to be shared in here or it will just become a global nightmare.
Using a singleton means you'll have a class that you can only ever have one instance of. If you put properties in that class any time you reference it it will be the same memory throughout the application execution.
http://blog.pixelbreaker.com/actionscript-3-0/as30-better-singletons
Marking the singleton class or individual properties as Bindable will make it so you can watch for the changes and call a function.
http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_8.html
Putting this together you have something like this:
[Singleton.as]
package
{
[Bindable]
public class Singleton
{
public var myListData:Array;
public static var instance:Singleton;
public static function getInstance():Singleton
{
if( instance == null ) instance = new Singleton( new SingletonEnforcer() );
return instance;
}
public function Singleton( pvt:SingletonEnforcer )
{
// init class
}
}
}
internal class SingletonEnforcer{}
Somewhere else you want to get a handle on this
[MyTitleWindow.as]
var instance:Singleton = Singleton.getInstance();
instance.myListData = [1,2,3];
[MyTitleWindowWithAList]
var instance:Singleton = Singleton.getInstance();
BindingUtils.bindSetter(funcUpdateList, instance, "myListData");
private function funcUpdateList(data:Object)
{
myList.dataProvider = data as Array;
}
Another option is to create an event that carries your data payload, dispatch that event from the first title window, and capture it, the problem with this is you have to register the listeners on the PopUpManager or SystemManager I believe because the TitleWindow's aren't direct children of the Application I believe.
Singletons are a bad idea and you should not get in the habit of using them. Instead, just dispatch an event from the View and catch it from something else that has access to your Service object.
Note that your Service should not be part and parcel of any View--the responsibility of a View is displaying data and capturing requests from the user to change the data, not communicating with a server.
For examples of an application written with this pattern in mind, check out
[Refactoring with Mate] (http://www.developria.com/2010/05/refactoring-with-mate.html) - The example has View source enabled
The same application done with RobotLegs - again, View Source is enabled.
Note that these are written against some popular frameworks, but they are written in such a way that you can easily replace that framework code with something else, even your own code.
For reference, here is the naiive implementation, where the service layer is being called directly in the Views. You couldn't call a different service without changing the Views, though the use of the static service means you could use it from elsewhere.
That static usage survived into the later examples, though today I would never write something depending on a globally accessible object. In part this is because I discovered Test Driven Development, and it is impossible to replace the "real" static object with an object that lets you isolate what you are testing. However, the fact that most of the code in the 2 "better" examples is insulated from that static object means that it is trivial to replace it with one that is provided some other way.
The lesson here is if you're going to use static, global objects, lock them away behind as much abstraction as you can. But avoid them if you're at all interested in best practice. Note that a Singleton is a static global object of the worst kind.

Mock methods not directly called in unit test with JMock

I have a method under test. Within its call stack, it calls a DAO which intern uses JDBC to chat with the DB. I am not really interested in knowing what will happen at the JDBC layer; I already have tests for that, and they work wonderfully.
I am trying to mock, using JMock, the DAO layer, so I can focus on the details this method under test. Here is a basic representation of what I have.
#Test
public void myTest()
{
context.checking(new Expectations() {
{
allowing(myDAO).getSet(with(any(Integer.class)));
will(returnValue(new HashSet<String>()));
}
});
// Used only to show the mock is working but not really part of this test.
// These asserts pass.
Set<String> temp = myDAO.getSet(Integer.valueOf(12));
Assert.assertNotNull(temp);
Assert.assertTrue(temp.isEmpty());
MyTestObject underTest = new MyTestObject();
// Deep in this call MyDAO is initialized and getSet() is called.
// The mock is failing to return the Set as desired. getSet() is run as
// normal and throws a NPE since JDBC is not (intentionally) setup. I want
// getSet() to just return an empty set at this layer.
underTest.thisTestMethod();
...
// Other assertions that would be helpful for this test if mocking
// was working.
}
It, from what I have learned creating this test, that I cannot mock indirect objects using JMock. OR I am not seeing a key point. I'm hoping for the second half to be true.
Thoughts and thank you.
From the snippet, I'm guessing that MyTestObject uses reflection, or a static method or field to get hold of the DAO, since it has no constructor parameters. JMock does not do replacement of objects by type (and any moment now, there'll be a bunch of people recommending other frameworks that do).
This is on purpose. A goal of JMock is to highlight object design weaknesses, by requiring clean dependencies and focussed behaviour. I find that burying DAO/JDBC access in the domain objects eventually gets me into trouble. It means that the domain objects have secret dependencies that make them harder to understand and change. I prefer to make those relationships explicit in the code.
So you have to get the mocked object somehow into the target code. If you can't or don't want to do that, then you'll have to use another framework.
P.S. One point of style, you can simplify this test a little:
context.checking(new Expectations() {{
allowing(myDAO).getSet(12); will(returnValue(new HashSet<String>()));
}});
within a test, you should really know what values to expect and feed that into the expectation. That makes it easier to see the flow of values between the objects.