Javafx and the Observer pattern - updating a UI - javafx

I am trying to implement the Observer pattern in a JavaFx application. I've never asked a question here but this is driving me a bit crazy.
Essentially I'm trying to use the Observer pattern to monitor a class that's parsing a file of phone numbers, and update the UI automatically as the file is parsed.
Before I get to my questions, here is my code:
Abstract class Observer.java
public abstract class Observer
{
public PhoneBook numbers;
public abstract void update();
}
I have a class that implements this:
public class PhoneBookObserver extends Observer {
public PhoneBookObserver(PhoneBook numbers)
{
this.numbers = numbers;
this.numbers.attach(this);
}
#Override
public void update()
{
System.out.println(""NUMBER - : " + numbers.GetNumbers());
}
}
In the class doing the parsing, I've created a new PhoneBookObserver
public PhoneBook ParsePhoneBook()
{
PhoneBook nums= new PhoneBook();
PhoneBookObserver p = new PhoneBookObserver(nums);
// ... Parsing of file - works fine
return nums;
}
Currently this runs and my println from update() in PhoneBookObserver is output.
My questions are:
Can the update method of PhoneBookObserver update my UI for me? How would it access JavaFx elements in my controller?
Can I just make my controller an observer, override update() and use that to update my UI elements from within my controller? Is that bad?

To directly answer your question, I would probably implement the Observer as an inner class in the controller. Then it has access to everything in the controller.
Assuming here PhoneBook defines a method of the form
public List<PhoneNumber> getPhoneNumbers() ;
then you could do:
public class Controller {
#FXML
private ListView<PhoneNumber> phoneNumberList ;
private PhoneBook numbers = new PhoneBook() ; // or initialize from elsewhere
public void initialize() {
numbers.attach(new PhoneBookObserver(numbers));
// ...
}
private class PhoneBookObserver extends Observer {
PhoneBookObserver(PhoneBook numbers) {
this.numbers = numbers ;
}
#Override
public void update() {
phoneNumberList.getItems().setAll(numbers.getPhoneNumbers());
}
}
}
Note that in
public abstract class Observer
{
public PhoneBook numbers;
public abstract void update();
}
the field numbers really serves no purpose, as the only method doesn't use it. So you could remove it (subclasses can define such a field if they need). Then you may as well make it an interface, and since it only has one method, it's a #FunctionalInterface:
#FunctionalInterface
public interface Observer {
public void update() ;
}
and now it can be implemented with a lambda expression, so the implementation is so thin that you basically stop having any issues with "accessing the UI":
public class Controller {
#FXML
private ListView<PhoneNumber> phoneNumberList ;
private PhoneBook numbers = new PhoneBook() ; // or initialize from elsewhere
public void initialize() {
numbers.attach(() -> phoneNumberList.getItems().setAll(numbers.getPhoneNumbers());
// ...
}
}
Finally, note that JavaFX Properties and observable lists basically already provide an implementation of the observer pattern, so you're pretty much reinventing the wheel here. You could just have
public class PhoneBook {
private final ObservableList<PhoneNumber> numbers;
public ObservableList<PhoneNumber> getPhoneNumbers() {
return numbers ;
}
}
and then
public class Controller {
#FXML
private ListView<PhoneNumber> phoneNumberList ;
private PhoneBook numbers = new PhoneBook() ; // or initialize from elsewhere
public void initialize() {
phoneNumberList.setItems(numbers.getPhoneNumbers());
}
}
and the list view will observe the (already-observable) list of numbers for you. There is no real need for your Observer or PhoneBookObserver.

Related

AggregateMember inheritance: No handler was subscribed to command

I have the below aggregate which contains an aggregate member.
#Aggregate
public class CpaAggregate {
#AggregateIdentifier
private String externalId;
#AggregateMember
private Entity entity;
public CpaAggregate() {
}
#CommandHandler
public CpaAggregate(CreateCpaCommand cmd) {
AggregateLifecycle.apply(new CpaCreatedEvent(...));
}
#EventSourcingHandler
protected void on(CpaCreatedEvent evt) {
....
}
}
public class Entity {
#EntityId
private String entityId;
private Set<Identifier> identifiers = new HashSet<>();
public Entity() {
}
#EventSourcingHandler
public void on(IdentifiantUpdatedEvent evt) {
...
}
}
public class Laboratory extends Entity {
private OperatingSystem operatingSystem;
public Laboratory() {
}
#CommandHandler
public void handle(UpdateIdentifierLABCommand cmd) {
AggregateLifecycle.apply(new IdentifiantUpdatedEvent(....));
}
}
.
commandGateway.sendAndWait(new UpdateIdentifierLABCommand(...));
When i send a command to update an identifier of entity of type laboratory, i get this error
org.axonframework.commandhandling.NoHandlerForCommandException: No
handler was subscribed to command [UpdateIdentifierLABCommand]
I would model your CpaAggregate slightly differently, Aymen.
Instead of using the generic Entity aggregate member, I'd go for more specific entities like the Laboratory instance.
This is, for one, a lot more clear modeling-wise, as the model structure becomes clearer. Secondly, Axon Framework will move up into parent class for specifics. So, you can still have common information in an Entity class, like entity identifiers, command handlers, and event sourcing handlers.
I would thus adjust it like so:
#Aggregate
public class CpaAggregate {
#AggregateIdentifier
private String externalId;
#AggregateMember
private Laboratory laboratory;
public CpaAggregate() {
}
#CommandHandler
public CpaAggregate(CreateCpaCommand cmd) {
AggregateLifecycle.apply(new CpaCreatedEvent(...));
}
#EventSourcingHandler
protected void on(CpaCreatedEvent evt) {
....
}
}
This should ensure Axon Framework spots the command handler inside the aggregate member too, by the way.

Can multiple KafkaListener classes listen to the same topic?

I have kafka topic that contains multiple events (of different types), and I'd like to handle those events in different handler classes within single application. So my question is - can I create two classes(spring components) that consumes same topic, but each of them handles different events (from that same topic)?
#Component
#KafkaListener(topics = "topicA")
public class SomeClass {
#KafkaHandler
public void handleEventA(EventA eventA) {
}
}
#Component
#KafkaListener(topics = "topicA")
public class AnotherClass {
#KafkaHandler
public void handleEventB(EventB eventB) {
}
#KafkaHandler
public void handleEventC(EventC eventC) {
}
}
Normally you would have all the #KafkaHandlers in the same class.
You can do what you want, but each listener needs to be in a different consumer group and you need a default method to discard the events you are not interested in.
#Component
#KafkaListener(id = "some", topics = "topicA")
public class SomeClass {
#KafkaHandler
public void handleEventA(EventA eventA) {
}
#KafkaHandler(isDefault = true)
public void handleOthers(Object others) {
// discard
}
}
#Component
#KafkaListener(id = "another", topics = "topicA")
public class AnotherClass {
#KafkaHandler
public void handleEventB(EventB eventB) {
}
#KafkaHandler
public void handleEventC(EventC eventC) {
}
#KafkaHandler(isDefault = true)
public void handleOthers(Object others) {
// discard
}
}
Just share a finding after we tried this approach, the logic of listener container is executed per #KafkaListener class. i.e. the associated logic of FilterStrategy and MessageConverter will be run multiple times for the same event, which is probably not what we want.

JavaFX Property's invalidate() method not called with binding

I'm trying to make a custom control in JavaFX using some binding feature. This is my problem: I have a class with a DoubleProperty that I use to calculate the position of an element inside my custom control. Here is the code:
public class CustomControl extends Region {
private DoubleProperty positionProperty;
public CustomControl() {
positionProperty= new DoublePropertyBase(0.0) {
#Override public Object getBean() { return CustomControl.this; }
#Override public String getName() { return "position"; }
#Override protected void invalidated() { updatePostion(); }
};
}
public DoubleProperty positionProperty() { return positionProperty; }
public double getPosition() { return positionProperty.get(); }
public void setPosition(double value) { positionProperty.set(value); }
private void updatePosition() {
double value = doubleProperty.get();
//compute the new position using value
}
}
In my application i have two CustomControls and i want that when i call the method setPosition() on the first of them, the second one updates the position of its component as well. To do so I binded the positionProperty of the two CustomControls like this:
CustomControl control1 = new CustomControl();
CustomControl control2 = new CustomControl();
control2.positionProperty.bind(control1.positionProperty);
Then when I call for example
control1.setPosition(50.0);
only the position of the component of control1 is updated, indeed when i call the method setPosition(), the method invalidated() of the positionProperty of control1 is actually called, but not the one of the positionProperty of contol2 as I espected. How shoul i achieve what i want? Thank you!
PS: I also noticed that using the method bindBidirectional() instead of bind() works, but shouldn't it work using only bind() too?
EDIT: example code is available here: https://luca_bertolini#bitbucket.org/luca_bertolini/customcontrolexample.git
JavaFX uses lazy evaluation for all bindings, which means that when a change occurs on your out.positionProperty object, the new value is not immediately taken into account. This happens later, if and only when the value is subsequently requested.
Try this:
out.positionProperty().addListener(new InvalidationListener() {
#Override
public void invalidated(final Observable observable) {
// System.out.println("It must go now.");
}
});
and you will see that this time your code works as you want.

Toolbar with SearchView temporary filtering RecyclerView

I need to implement search functionality inside my android app which uses toolbar, SlidingTabLayout and ViewPager that holds fragments. Inside each fragment there is a RecyclerView with list of items.
RecyclerView data is static defined in separate class (DataAccess.java) and those lists are updated and RecyclerView gets refreshed just by calling (without passing new data)
mRecyclerView.getAdapter().notifyDataSetChanged();
Is there any simple way to temporary filter RecyclerView without changing the data and after the user presses return button inside Toolbar to remove the filter and show inital list.
Before pressing Search icon inside toolbar menu:
So when the user is typing "Josip..." the filter will be active
and after he presses the X button in SearchView the user will get the same data as before without filter.
#Override
public boolean onQueryTextChange(String newText) {
// filter data (temporary remove all items from DataAccess.list that don't .startsWith(newText)
}
#Override
public boolean onQueryTextSubmit(String query)
// Doesn't help if I revert deleted items here
}
#Override
public boolean onQueryTextSubmit(String query){
((ItemAdapter) myRecList.getAdapter()).setFilter(query)
}
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> {
private List<String> visibleObjects;
private List<String> allObjects;
.....
public void flushFilter(){
visibleObjects=new ArrayList<>();
visibleObjects.addAll(allObjects);
notifyDataSetChanged();
}
public void setFilter(String queryText) {
visibleObjects = new ArrayList<>();
constraint = constraint.toString().toLowerCase();
for (String item: allObjects) {
if (item.toLowerCase().contains(queryText))
visibleObjects.add(item);
}
notifyDataSetChanged();
}
}
I wanted to add as comment but due to less reputation...I am answering post.
This method works fine if (item.toLowerCase().contains(queryText)) but what to do if match is not found in first iteration.then it will go in else part without looping throughout allObjects list...
for (RouteByATMList.Route_ATM item: Main_ATMItemList)
{
if (item.ATMNumber.contains(queryText)) {
visibleObjects.add(item);
}else {
Toast.makeText(mContext,"No search result found!",Toast.LENGTH_SHORT).show();
break;
}
}
I got the answer from my superior ,hope it helps.
public void setFilter(String queryText) {
visibleObjects = new ArrayList<>();
for (RouteByATMList.Route_ATM item: Main_ATMItemList)
{
if (item.ATMNumber.contains(queryText))
{
visibleObjects.add(item);
}
}
if(visibleObjects.size()==0){
Toast.makeText(mContext,"No search result found!",Toast.LENGTH_SHORT).show();
}
notifyDataSetChanged();
Log.e("dataset changed","dataset changed");
}
I don't oppose the given and accepted answer. There is a room for possible performance pitfalls. One should make use of Filterabe interface. Having this implemented will behave as ol'good ListView that did the filtering asynchronously. Then all you need is to write your own Filter and instantiate it in the overridden getFilter() method;
In my case I used Filter to sort an adapter of many (yeah, many many) items. It was junky sorting it on UI-thread.
So I had this abstract class
public abstract class BaseFilterableRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> implements Filterable {
private Context mContext;
public BaseFilterableRecyclerViewAdapter(Context context) {
this.mContext = context;
}
public abstract void sort(SortingFilter.Sort sortingStrategy);
//...Other methods
}
And the class that inherit:
public class ItemAdapter extends BaseFilterableRecyclerViewAdapter<RecyclerView.ViewHolder>{
//... RecyclerView methods
#Override
public Filter getFilter() {
return new SortingFilter(mData) {
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null) {
int last = mData.size();
mData = (List<Product>) results.values;
notifyDataSetChanged();
}
}
};
}
#Override
public void sort(SortingFilter.Sort sortingStrategy) {
getFilter().filter(sortingStrategy.toString());
}
}

Proper way of using Unit of Work with unity injection

I am using unity, entity framework 4 with POCO classes, repository pattern for DAL and services for Business Logic control.
I also want to use Unit of Work so I can package together CRUD operations which I perform on different services and then commit them all together.
My question is what would be the proper way to inject the Unit Of Work mechanism into my application using Microsoft Unity?
I understand that I can put the IUnitOfWork together with the repository on the constructor of the proper service and then if Unity mapping is specified it would auto initiate the proper instances, but this way I do not pass the global unit of work but rather create a new instance on each level, which can't be a smart way to do it (actually the repository is initiated even before the service).
What am I missing? (Attached is constructor code as I wrote it now of service and its repository).
U also understand that I can use Unity's ParameterOverrides method to take some global instance of Unit of Work (lets say from my aspx.cs file) and pass it into the service and then into the repository. But it seems a bit lame. Is this my only option?
Thanks
public class GenericRepository<T> : IUnitOfWorkRepository, IGenericRepository<T> where T : BaseEntity, IAggregateRoot
{
private IUnitOfWork _uow;
/// <summary>
/// Returns the active object context
/// </summary>
private ObjectContext ObjectContext
{
get
{
return ObjectContextManager.GetObjectContext();
}
}
public GenericRepository(IUnitOfWork uow)
{
_uow = uow;
}
//blahhhh...
public void Add(T entity)
{
_uow.RegisterNew(entity, this);
}
public void Delete(T entity)
{
_uow.RegisterRemoved(entity, this);
}
//.....blah blah....
public void PersistCreationOf(IAggregateRoot entity)
{
this.ObjectContext.AddObject(GetEntitySetName(), entity);
}
public void PersistUpdateOf(IAggregateRoot entity)
{
// Do nothing as EF tracks changes
}
public void PersistDeletionOf(IAggregateRoot entity)
{
this.ObjectContext.DeleteObject(entity);
}
}
public class CategoryRepository : GenericRepository<XComSolutions.FB.Domain.Model.Entities.Category>, ICategoryRepository
{
public CategoryRepository(IUnitOfWork uow)
: base(uow)
{ }
}
public class CategoryService : ICategoryService
{
public int myID {get; set;}
private ICategoryRepository _categoryRepository;
private IUnitOfWork _uow;
public CategoryService(ICategoryRepository categoryRepository,
IUnitOfWork uow)
{
_categoryRepository = categoryRepository;
_uow = uow;
}
public List<Category> GetAll()
{
return _categoryRepository.GetAll();
}
}
Define an IUnitOfWorkFactory and inject that in your services:
public class Service
{
private readonly IUnitOfWorkFactory factory;
public Service(IUnitOfWorkFactory factory)
{
this.factory = factory;
}
public void DoOperation()
{
using (UnitOfWork context = this.factory.CreateNew())
{
this.DoSomeStuff(context);
this.DoMoreStuff(context);
context.SubmitChanges();
}
}
}
What I think you need to do is to define unit of work factory. You register this factory with your DI container and you resolve for this factory every time you need your unit of work. Then you get unit of work from the factory, work with it and let it go. You often will see that you need your unit of work within a scope of single method or single class. This article discuss Unit of Work pattern in connection with Entity Framework: http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

Resources