Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Java - Notifying a method of a user action in a different plugin

Options
  • 22-10-2016 9:51pm
    #1
    Registered Users Posts: 8,197 ✭✭✭


    Hi,

    I’m trying to write some Java and am having some difficulty in getting the structure of my code correct.

    What I’m trying to do is to get Class A to perform an action when Class B executes a certain method (due to a certain user action occurring). Class A and Class B are in different plugins.

    What I’ve been advised to do is to create an interface class which contains three methods. This interface class will be implemented in Class B. It will allow Class A to receive notifications from Class B when the user action has occurred and then trigger it to go off and perform various tasks.

    The first method will allow Class A to register to receive notifications from Class B.
    The second method will allow Class B unregister to stop receiving the notifications from Class B.
    The third method will inform Class A that the user performed the specified action.

    Do I need to use listeners for this? My understanding was that I could do this without them. I’ve checked and each class currently has no visibility of the other class. I'm using the Eclipse IDE.



    I suspect that some might query why I need to register and then send the information (i.e. just have the inform method) but that seems to be the architecture.


    Any ideas as to how I could implement this suggested implementation?


    Thanks.


Comments

  • Registered Users Posts: 403 ✭✭counterpointaud


    Hi,

    I’m trying to write some Java and am having some difficulty in getting the structure of my code correct.

    What I’m trying to do is to get Class A to perform an action when Class B executes a certain method (due to a certain user action occurring). Class A and Class B are in different plugins.

    What I’ve been advised to do is to create an interface class which contains three methods. This interface class will be implemented in Class B. It will allow Class A to receive notifications from Class B when the user action has occurred and then trigger it to go off and perform various tasks.

    The first method will allow Class A to register to receive notifications from Class B.
    The second method will allow Class B unregister to stop receiving the notifications from Class B.
    The third method will inform Class A that the user performed the specified action.

    Do I need to use listeners for this? My understanding was that I could do this without them. I’ve checked and each class currently has no visibility of the other class. I'm using the Eclipse IDE.



    I suspect that some might query why I need to register and then send the information (i.e. just have the inform method) but that seems to be the architecture.


    Any ideas as to how I could implement this suggested implementation?


    Thanks.

    On reading that, my first instinct would be to tell you to Google "Observer Pattern in Java". If this is part of college coursework, though, it's possible that your lecturer wants you to achieve this in a specific way, so bear that in mind.


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    If this is part of college coursework

    If it was I wouldn't be posting about it on a Saturday night. New job. In over my head. Very stressed.:(


  • Registered Users Posts: 403 ✭✭counterpointaud


    If it was I wouldn't be posting about it on a Saturday night. New job. In over my head. Very stressed.:(

    Been there. Haven't written Java in quite a while, but if you can post some code, maybe myself or someone else here can help. It seems to me that the advice you got is solid enough, but it may have left out some details (depending on the specifics of your situation).

    *EDIT* I get that you probably can't post company code, but maybe make a simplified example of what you are trying to achieve?


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    I'll try to post something up in the morning. I've got no access to it at the weekend and I'm not sure that I could produce a feasible replica anyhow given the size of the items.


  • Registered Users Posts: 403 ✭✭counterpointaud


    ok fair enough, kind of confused by the use of the word 'plugins', are there any frameworks or application containers in use here? any details would help. is this a web app?


  • Advertisement
  • Registered Users Posts: 403 ✭✭counterpointaud


    I was thinking of something along these lines, but maybe there's a reason you can't use this pattern.
    import java.util.List;
    import java.util.ArrayList;
    
    public class Main
    {
      public static void main(String[] args)
      {
        B subject1 = new B();
        A observer1 = new A(subject1);
        subject1.simulateUserEvent(new Event("boom!"));
      }
    }
    
    abstract class Observer {
       protected Subject subject;
       public abstract void notify(Event event);
    }
    
    interface Subject {
      public void register(Observer observer);
      public void deRegister(Observer observer);
    }
    
    class Event {
      private String message;
      public Event(String message){
        this.message = message;
      }
      
      public String getMessage(){
        return this.message;
      }
    }
    
    class A extends Observer {
      
      public A(Subject subject){
        this.subject = subject;
        this.subject.register(this);
      }
      
      @Override
       public void notify(Event event) {
          System.out.println( "Received " + event.getMessage()); 
       }
    }
    
    class B implements Subject {
      private List<Observer> observers = new ArrayList<Observer>();
    
      public void simulateUserEvent(Event event) {
        notifyAllObservers(event);
      }
    
      public void register(Observer observer){
        observers.add(observer);		
      }
      
      public void deRegister(Observer observer){
        // deregister logic here		
      }
    
      private void notifyAllObservers(Event event){
        for (Observer observer : observers) {
          observer.notify(event);
        }
      } 
    }
    


  • Registered Users Posts: 6,150 ✭✭✭Talisman


    Are you familiar with the Observer or Publish-Subscribe patterns?


  • Registered Users Posts: 11,262 ✭✭✭✭jester77


    The observer pattern would work good here. You could use RxJava and create an Observer around whatever the action is in Class B. Class A can then subscribe to it and do whatever actions it needs depending on what is emitted by the Observable/Single.


  • Registered Users Posts: 6,150 ✭✭✭Talisman


    @funkey_monkey: Have you looked for this on the Eclipse website?

    Notes on the Eclipse Plug-in Architecture - Listener Extensions and the Observer Pattern


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Hi everyone,

    Thanks for the replies. I'll try to explain what I'm at in more detail without giving things away, if that makes sense.
    Class A implements InterfaceB
    
       C.register(?);
    
       C.unregister(?);
    
       void DoSomethingBasedOnClassC()
       {
          Do stuff
       }
    
    

    Class C
    {
    
       private List <InterfaceB> bListener;
    
       ...
    
       void register (InterfaceB listener)
       { 
         this.bListener.add(listener);
       }
    
       void unregister (InterfaceB listener)
       { 
          for (Iterator <InterfaceB> it = this.bListener.iterator();
             it.hasNext());
          
             InterfaceB x = it.next();
             if (x.equals(listener))
                it.remove();
       }
    
       void doStuff(int x, int y)
       {
          if (this.bListener != null && this.bListener.isEmpty()
          {
             Do something
          }
          else
          {
             for (InterfaceB listener : this.bListener)
             {
                A.DoSomethingBasedOnClassC. 
             }
          }
       }
       
       ...
    }
    

    How do I register class A using the reg/unreg methods? That is my problem.

    Classes A and B are in different plugins.


  • Advertisement
  • Registered Users Posts: 52 ✭✭TheAbstracter


    Classes A and B are in different plugins.

    What is a plugin? Are you using a specific framework or something?


  • Registered Users Posts: 403 ✭✭counterpointaud


    Hi everyone,

    Thanks for the replies. I'll try to explain what I'm at in more detail without giving things away, if that makes sense.

    If class C is the one with the register/deregister methods, then surely it is class C that implements interfaceB, no? What does interfaceB look like?

    Please take a closer look at the code I posted, it will run as is.

    To take my suggested approach, you need a class that has visibility of both subject and observer to wire them both up. Also still not sure what you mean by 'plugins'.


  • Registered Users Posts: 6,150 ✭✭✭Talisman


    What is a plugin? Are you using a specific framework or something?
    Eclipse


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Got it going. Missed a project specific line of code.
    Two days wasted. I can't charge this time to them for being an idiot.
    Learning curve.

    Thanks and apologies for not being able to give a full solution.

    Where I register for updates I needed to perform an additional registration.


  • Registered Users Posts: 403 ✭✭counterpointaud


    Two days wasted. I can't charge this time to them for being an idiot.

    Did you claim to be experienced in writing eclipse plugins when you interviewed? This is a little different from straight Java, some onboarding time is to be expected IMO.


  • Registered Users Posts: 52 ✭✭TheAbstracter


    Talisman wrote: »

    Oh right, OP mentioned they were using Eclipse alright but hadn't thought they were writing a plugin for Eclipse itself.


  • Registered Users Posts: 403 ✭✭counterpointaud


    Oh right, OP mentioned they were using Eclipse alright but hadn't thought they were writing a plugin for Eclipse itself.

    Yep, I also assumed they meant Eclipse the IDE, as opposed to Eclipse the OSS Platform (or whatever).


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Thanks - that bit is sorted now. Continually encountering problems that I struggle to solve.

    I'm not sure that I'm a good fit for this role, but I'll stick it out until the end of the contract and I hope to start some training soon to help ease things and make a new job easier to come by.

    :(


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Can you have radio buttons in a group with none defaulted on?

    I have a design request to create a number of radio buttons held inside a group defaulted all to off.

    I could do it via checkbox but that is not what I've been asked.

    I know that when you group radio buttons one is always defaulted to on. Can i override this or get something that looks similar to a group to contain these buttons, but allow me to alter the details independently.

    When i remove the group i can default them to off but i lose the border and label of the group and the functionality.


  • Registered Users Posts: 6,150 ✭✭✭Talisman


    Radio buttons should always have a selection, it's a user experience thing.

    Radio Buttons: Select One by Default or Leave All Unselected?


  • Advertisement
  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    That is what i thought, so I hope I'll get approval to change the design.


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    From reading SWT a developers notebook, you create afake button, hide it and set is selection to true.
    However, making the button invisible on XP removes it from the group.


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    Just been reading up on handling the radio buttons. It seems odd that you have to put the listeners onto the individual buttons as opposed to onto the group. Makes he code look messy IMO.

    I've written some code whereby a dialog updates a field in the calling class by means of an accessor. This is done when the OK button is pressed. However, when the Cancel button is pressed, nothing should happen. Therefore, upon return to my calling class I need to know if the data in the field has been refreshed or is stale data from a previous cycle.

    The field is intended to return a String.

    What I was wondering was, do I create a default value on the field and update it only in the OK Pressed method. This would allow me to check for it upon return into the calling method. If the field value is not altered then I know cancel was pressed, otheriwse I know that it has been updated via the OK button.

    Is this the correct way to handle the buttons?

    Something like:
    public ClassA()
    {
       ...
       private String value;
       ...
    
       public ClassA()
       {
          super();
          this.value = "Default";
          ...
       }
    
       ...
    
       public void callDialog()
       {
          this.setValue("Default");
    
          dialog.open();
    
          if (!this.getValue().equals("Default")
          {
             // this.value has been updated.  Handle the return value
          }
          else
          {
             // this.value is unchanged.  Do nothing
          }
       }
    
       pubilc void setValue(final String theValue)
       {
          this.value = theValue;
       }
    
       public String getValue()
       {
          return this.value;
       }
    }
    
    public ClassDialog()
    {
       ...
    
       protected void okPressed()
       {
          ...
          classA.setValue(dialogValue);
       }
    
       protected void cancelPressed()
       {
          ...
       }
    }
    


  • Registered Users Posts: 8,197 ✭✭✭funkey_monkey


    I've went with the above in order to get some progress.

    I'm trying to avoid posting regularly on here, but I'm trying to get some progress before a deadline in a few days.

    I have a record which amongt things contains a number of strings - Name1, Name2, Name3. They can have a limited range of values - which are equally application across the three strings.

    If Name1 = "Builder" and then I select Name3 to equal "Builder", I would want Name1 = "Unemployed". Now, this is easy to do in a forced way with a number of if statements. However, is there a more elegant solution.

    Currently, I've got:
    public Class ClassA()
    {
       ...
    
       public void setSiteName(tradesman)
       {
          ...
          
          // Update person to a site job
          if (record != null)
          {
             // My plan was to check here for the name already being assigned to a job
             // and then resetting it to default using a number of if statements - very unweildy :(
             if (tradesman.equals(record.getBuilderName())
                record.setBuilderName("Unemployed");
             ...
    
             if (getJob().equals("Builder")
                record.setBuilderName(tradesman);
             else if (getJob().equals("Joiner")
                record.setJoinerName(tradesman);
             else if (getJob().equals("Plumber")
                record.setPlumberName(tradesman);
    
    

    * Note, Yes I could use a Switch statement, but I want to control the jobs from a central location and this is not supported by Switch statements - hardcoding as per above has been done for quickness.


  • Registered Users Posts: 6,150 ✭✭✭Talisman


    It may be beyond your control but instead of using strings why not use an enum type as the range of values is predefined:
    public enum Job { UNEMPLOYED, BUILDER, JOINER, PLUMBER };
    

    An array would be a more efficient data structure than Name1, Name2, Name3.
    String[] Jobs = { "Unemployed", "Builder", "Joiner", "Plumber"};
    String defaultString = Jobs[0];
    
    String tradesman = "Builder";
    
    /*
     *  Returns -1 or index value of matching string.
     */
    public int find(String[] array, String value) {
        int result = -1;
        for (int ix=0; ix<array.length; ix++) 
             if (array[ix].equals(value)) {
                 result = ix;
                 break;
             }
        return result;
    }
    
    
    // check 
    int idx = find(array, tradesman);
    if (idx > -1) {
       array[idx] = defaultString;
    }
    


Advertisement