I have a code in Java, where I should call the overriden method from the constructor of base class.
I understand that it may cause problems according to many references for example:
Calling an overridden method from a parent class ctor
and also
https://medium.com/#rufuszh90/effective-java-item-17-design-and-document-for-inheritance-or-else-prohibit-it-be6041719fbc
The question I have which pattern to use instead?
Adding sample code here is a Task constructor:
public <T extends AbstractCommon & IParent> Task(T parent, String uuid, String version, Set<AbstractNode> exceptions) throws Exception {
Event tef = getExecutionFinishedEvent();
Event tep = getExecutionInProgressEvent();
Event tefailed = getExecutionFailed();
Event tefinishedonallnodes = getExecutionFinishedOnAllNodesEvent();
Event tTimeout = getTimeoutEvent();
Event tNotAllNodesAreAcessible = getNotAllNodesAreAccessible();
Event tNotAllObjectsAreAvailable = getNotAllObjectsAreAvailable();
}
Here is the extending class AbstractRemoteTask and there are some others.
public abstract class AbstractRemoteTask extends Task implements InterNodeProcessor {
public AbstractRemoteTask() {
}
#JsonIgnore
#Override
protected Event getExecutionFinishedEvent() {
return getEvent(Event.EventType.EXECUTION_FINISHED_LOCAL);
}
#JsonIgnore
#Override
protected Event getExecutionFinishedOnAllNodesEvent() {
return getEvent(Event.EventType.EXECUTION_FINISHED_ON_ALL_NODES);
}
#Override
protected Event getExecutionInProgressEvent() {
return getEvent(Event.EventType.EXECUTION_IN_PROGRESS);
}
#JsonIgnore
#Override
protected Event getExecutionFailed() {
return getEvent(Event.EventType.EXECUTION_FAILED);
}
#JsonIgnore
#Override
protected Event getTimeoutEvent() {
return new RemoteEvent(this, getNodeUuid(), Event.EventType.TIMEOUT);
}
#JsonIgnore
#Override
protected Event getNotAllNodesAreAccessible() {
return new RemoteEvent(this, getNodeUuid(), Event.EventType.NOT_ALL_NODES_ARE_ACCESSIBLE);
}
#JsonIgnore
#Override
protected Event getNotAllObjectsAreAvailable() {
return new RemoteEvent(this, getNodeUuid(), Event.EventType.NOT_ALL_OBJECTS_ARE_AVAILABLE);
}
So the question is what is the best pattern to implement this? As the way it is implemented is not recommended.
Related
I have a view model class, SampleViewModel, that has an observer, DataSourceObserver, whose event's (e.g. onDataUpdated) are triggered from a private method of the view model's data source class.
I am trying to add a unit test for how the view model's observer handles the onDataUpdated.
#HiltViewModel
public class SampleViewModel extends ViewModel {
private final #NonNull ViewModelDataSource viewModelDataSource;
private final #NonNull ViewModelDataSource.DataSourceObserver observer = new ViewModelDataSource.DataSourceObserver() {
#Overrode
public void onDataUpdated(){
// some sort of handling
}
};
#Inject
public SampleViewModel(final #NonNull ViewModelDataSource dataSource){
viewModelDataSource = dataSource;
viewModelDataSource.setObserver(observer);
}
}
public class ViewModelDataSource{
public interface DataSourceObserver {
void onDataUpdated();
}
private final ContactObservers.Observer contactObserver = new ContactObservers.Observer(){
#Override
public void onContactUpdated(){
if (myObserver != null){
myObserver.onDataUpdated();
}
}
};
private #Nullable DataSourceObserver myObserver;
#Inject
public ViewModelDataSource(){
// other initialization here
}
public void setObserver(DataSourceObserver observer){
myObserver = observer;
}
}
I have Mockito for mocking/stubbing objects, but I have no idea how to approach such a problem so that I can at least trigger something like observer.onDataUpdated and verify the method calls within the handling of onDataUpdated
Found a solution to use ArgumentCaptor to capture the initialized observer in the view model when viewModelDataSource.setObserver(observer); is called.
In my unit test:
ArgumentCaptor<ViewModelDataSource.DataSourceObserver> capturedObserver = ArgumentCaptor.forClass(ViewModelDataSource.DataSourceObserver.class);
SampleViewModel viewModel = new SimpleViewModel( ...);
assertNotNull(capturedObserver);
So I'm using the Observer pattern in my app in order to get notified of changes in another class without having to look for them.
I have a Singleton class which extends Observable. Inside this class I have two CountDownTimer type variables. Eachs of these contains two methods: onTick() and onFinished().
Let's call those Timers A and B for the sake of simplicity.
Every time A.onTick(), A.onFinished(), B.onTick(), B.onFinished() are called, I must call notifyObservers() to notify my Observer that something has changed.
Until here everything works fine. The problem is that I know something has changed, but I don't know what exactly has changed. Depending on which one notified me, I must execute some code on the Observer side.
How do I know which of these methods notified me?
Use LiveData instead of Observable. LiveData is quite useful because not only it's observable but also it binds to your activity's lifecycle so you don't have to worry about handling it yourself.
Maybe this example will help you:
public class MyTimerWrapper {
public static MyTimerWrapper getInstance() {
// Your singleton logic
createTimers();
return instance;
}
private CountDownTimer timerA;
private CountDownTimer timerB;
private MutableLiveData<TimerEvent> timerALiveData = new MutableLiveData<TimerEvent>();
private MutableLiveData<TimerEvent> timerBLiveData = new MutableLiveData<TimerEvent>();
public LiveData<TimerEvent> startTimerA() {
timerA.start();
return timerALiveData;
}
public LiveData<TimerEvent> startTimerB() {
timerB.start();
return timerBLiveData;
}
private void createTimers() {
createTimerA();
createTimerB();
}
private void createTimerA() {
timerA = new CountDownTimer(30000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
// If you're running on another thread
timerALiveData.postValue(TimerEvent.TICK);
// Otherwise
timerALiveData.setValue(TimerEvent.TICK);
}
#Override
public void onFinish() {
// If you're running on another thread
timerALiveData.postValue(TimerEvent.FINISH);
// Otherwise
timerALiveData.setValue(TimerEvent.FINISH);
}
}
}
private void createTimerB() {
// Same as createTimerA, but with timerB
}
}
public enum TimerEvent {
TICK,
FINISH
}
Now to observe that data in your activity:
MyTimerWrapper timerWrapper = MyTimerWrapper.getInstance();
timerWrapper.startTimerA().observe(this, new Observer {
#Override
public void onChanged(TimerEvent timerEvent) {
// Here you'll be able to see whether timerA is ticking or finished
}
})
You can create a custom EventType class and pass it to Observable.notifyObservers(Object arg):
public class EventType {
String eventType; //"onTick" or "onFinish"
TimerType timerType;
EventType(String eventType, TimerType timerType){
this.eventType = eventType;
this.timerType = timerType;
}
}
TimerType is an enum type:
public enum TimerType {
A,
B;
}
and create TimerA and TimerB classes extending CountDownTimer:
private class TimerA extends CountDownTimer {
final EventType onTickEvent = new EventType("onTick", TimerType.A);
final EventType onFinishEvent = new EventType("onFinish", TimerType.A);
#Override
public void onTick(long millisUntilFinished) {
notifyObservers(onTickEvent);
}
#Override
public void onFinish() {
notifyObservers(onFinishEvent)
}
}
The Observerwill receive the EventType instance via its update(Observable o, Object arg); in the arg argument
Please note: I am new in this subject.
Suppose I have a class Event.
public class Event {
//constructors, etc.
public void pathFollowed(int location) {
//this method could be called at any time
}
}
And a class called EventManager.
public class EventManager {
private int managerLocation;
private ArrayList<Event> events;
public EventManager() {
events = new ArrayList<Event>();
}
public void addEvent(Event e) {
//THIS IS THE AREA OF INTEREST
events.add(e);
}
}
In the "area of interest" comment, is there any way of setting the value of managerLocation whenever the Event e calls upon pathFollowed(int location). My goal is that when any of the Events in the events arraylist calls pathFollowed(int location) that managerLocation would be set to "location" ("location" referring to the input in the pathfollowed method).
I was originally thinking of over-riding the pathFollowed method, but then I realized this can't be done because by the time the event gets to the addEvent method, it is already instantiated and can't be changed in this manner.
Thanks in advance.
Maybe some kind of listener pattern?
public class Event {
private List<PathListener> pls; //Or just one if you know you'll only need one
//constructors, etc.
public void pathFollowed(int location) {
//this method could be called at any time
for(PathListener pl : pls)
pl.notifyLocation(location);
}
public addPathListener(PathListener pl) {
pls.add(pl);
}
}
EventManager:
public class EventManager implements PathListener {
private int managerLocation;
private ArrayList<Event> events;
public EventManager() {
events = new ArrayList<Event>();
}
public void addEvent(Event e) {
e.addPathListener(this);
events.add(e);
}
#Override
public notifyLocation(int location) { //Of the PathListener interface
managerLocation = location;
}
}
This is just a kind-of-generic example, because I don't know what your purpose is, but maybe it will get you thinking.
Given the following abstract class:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
and the following child class:
public class VersionResponseV1 extends BaseVersionResponse<VersionVOV1>
{
protected String testFieldOne;
protected String testFieldTwo;
public String getTestFieldOne() {
return testFieldOne;
}
public void setTestFieldOne(String value) {
this.testFieldOne = value;
}
public String getTestFieldTwo() {
return testFieldTwo;
}
public void setTestFieldTwo(String value) {
this.testFieldTwo = value;
}
#Override
public void populate(VersionVOV1 versionVO) {
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
I desire to do something like this from a calling method:
public void getVersionInfo(String version) {
BaseVO versionVO = null;
BaseVersionResponse<? extends BaseVO> baseVersionResponse = null;
baseVersionResponse = createVersionResponse(version);
versionVO = createVersionVO(version);
baseVersionResponse.populate(versionVO);
}
where createVersionResponse(...) and createVersionVO(...) look like this:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) {
BaseVersionResponse<? extends BaseVO> specificVersionResponse = null;
if (version.equalsIgnoreCase("V1")) {
specificVersionResponse = new VersionResponseV1();
} else if (version.equalsIgnoreCase("V2"))
specificVersionResponse = new VersionResponseV2();
return specificVersionResponse;
}
public BaseVO createVersionVO(String version) {
BaseVO versionVO = null;
if (version.equalsIgnoreCase("V1")) {
versionVO = new VersionVOV1();
} else if (version.equalsIgnoreCase("V2"))
versionVO = new VersionVOV2();
return versionVO;
}
and VersionVOV1 looks like this:
public class VersionVOV1 extends BaseVO {
private String fieldOne = null;
private String fieldTwo = null;
private String fieldThree = null;
public String getFieldOne() {
return fieldOne;
}
public void setFieldOne(String fieldOne) {
this.fieldOne = fieldOne;
}
public String getFieldTwo() {
return fieldTwo;
}
public void setFieldTwo(String fieldTwo) {
this.fieldTwo = fieldTwo;
}
public String getFieldThree() {
return fieldThree;
}
public void setFieldThree(String fieldThree) {
this.fieldThree = fieldThree;
}
}
My problem arises when I try to compile this line of code:
baseVersionResponse.populate(versionVO);
in getVersionInfo(...). I'm getting a message that looks like this:
The method populate(capture#3-of ?) in the type BaseVersionResponse is not applicable for the arguments (BaseVO)
on the populate method above.
My thought was (which is apparently incorrect) that since the baseVersionResponse is, at this point in the code, actually a specific child instance, that the class would know exactly which populate method to call from that specific child class.
What am I doing wrong here? Is there a better way to do this if this isn't the correct approach?
Thank you for your time!
Ok, I took a better look at this today. The problem is that the wildcard, while the right way to go, precludes you from doing:
BaseVO versionVO = createVersionVO(version);
Because the populate call wants an extension of BaseVO, not an actual BaseVO, which doesn't qualify. That means you can't pass that versionVO variable directly.
So, to keep the type checking in place, which I think is good because you'll always want an implementation, leave pretty much everything as-is above, and change your BaseVersionResponse class to something like:
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
So, populate method now takes a BaseVO, and there's a new getVersion method to do some explicit casting for us. This should be ok since we know that the factory will always supply the right thing, but if another caller doesn't, an IllegalArgumentException is thrown.
Now, in your response class implementation, change the populate method accordingly:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
So, we've changed the populate method to take BaseVO, and the getVersion method does the casting for us. All the other type checks still apply, and we're good to go.
The casting makes it feel not as clean, but for the factory approach you're using, it's really the only way (I can think of) to keep the guarantees made by the type declarations and the code pattern in tact.
Hope that helps!
If you just take out the capture of type (the "<?>"), and leave it unchecked, it should work just fine. Even using type Object would have compiled.
But, given your specific example, what you probably want is the method:
public BaseVersionResponse<?> createVersionResponse(String version)
Changed to:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
Then, instead of using
BaseVersionResponse<?>
use
BaseVersionResponse<? extends BaseVO>
Since you know that the return type will be one of those things that implements the interface/class.
Could you guys please help me find where I made a mistake ?
I switched from SimpleBeanEditorDriver to RequestFactoryEditorDriver and my code no longer saves full graph even though with() method is called. But it correctly loads full graph in the constructor.
Could it be caused by circular reference between OrganizationProxy and PersonProxy ? I don't know what else to think :( It worked with SimpleBeanEditorDriver though.
Below is my client code. Let me know if you want me to add sources of proxies to this question (or you can see them here).
public class NewOrderView extends Composite
{
interface Binder extends UiBinder<Widget, NewOrderView> {}
private static Binder uiBinder = GWT.create(Binder.class);
interface Driver extends RequestFactoryEditorDriver<OrganizationProxy, OrganizationEditor> {}
Driver driver = GWT.create(Driver.class);
#UiField
Button save;
#UiField
OrganizationEditor orgEditor;
AdminRequestFactory requestFactory;
AdminRequestFactory.OrderRequestContext requestContext;
OrganizationProxy organization;
public NewOrderView()
{
initWidget(uiBinder.createAndBindUi(this));
requestFactory = createFactory();
requestContext = requestFactory.contextOrder();
driver.initialize(requestFactory, orgEditor);
String[] paths = driver.getPaths();
createFactory().contextOrder().findOrganizationById(1).with(paths).fire(new Receiver<OrganizationProxy>()
{
#Override
public void onSuccess(OrganizationProxy response)
{
if (response == null)
{
organization = requestContext.create(OrganizationProxy.class);
organization.setContactPerson(requestContext.create(PersonProxy.class));
} else
organization = requestContext.edit(response);
driver.edit(organization, requestContext);
}
#Override
public void onFailure(ServerFailure error)
{
createConfirmationDialogBox(error.getMessage()).center();
}
});
}
private static AdminRequestFactory createFactory()
{
AdminRequestFactory factory = GWT.create(AdminRequestFactory.class);
factory.initialize(new SimpleEventBus());
return factory;
}
#UiHandler("save")
void buttonClick(ClickEvent e)
{
e.stopPropagation();
save.setEnabled(false);
try
{
AdminRequestFactory.OrderRequestContext ctx = (AdminRequestFactory.OrderRequestContext) driver.flush();
if (!driver.hasErrors())
{
// Link to each other
PersonProxy contactPerson = organization.getContactPerson();
contactPerson.setOrganization(organization);
String[] paths = driver.getPaths();
ctx.saveOrganization(organization).with(paths).fire(new Receiver<Void>()
{
#Override
public void onSuccess(Void arg0)
{
createConfirmationDialogBox("Saved!").center();
}
#Override
public void onFailure(ServerFailure error)
{
createConfirmationDialogBox(error.getMessage()).center();
}
});
}
} finally
{
save.setEnabled(true);
}
}
}
with() is only used for retrieval of information, so your with() use with a void return type is useless (but harmless).
Whether a full graph is persisted is entirely up to your server-side code, which is intimately bound to your persistence API (JPA, JDO, etc.)
First, check that the Organization object you receive in your save() method on the server-side is correctly populated. If it's not the case, check your Locators (and/or static findXxx methods) ; otherwise, check your save() method's code.
Judging from the code above, I can't see a reason why it wouldn't work.
It took me some time to realize that the problem was the composite id of Person entity.
Below is the code snippet of PojoLocator that is used by my proxy entities.
public class PojoLocator extends Locator<DatastoreObject, Long>
{
#Override
public DatastoreObject find(Class<? extends DatastoreObject> clazz, Long id)
{
}
#Override
public Long getId(DatastoreObject domainObject)
{
}
}
In order to fetch child entity from DataStore you need to have id of a parent class. In order to achieve that I switched "ID class" for Locator<> to String which represents textual form of Objectify's Key<> class.
Here is how to looks now:
public class PojoLocator extends Locator<DatastoreObject, String>
{
#Override
public DatastoreObject find(Class<? extends DatastoreObject> clazz, String id)
{
Key<DatastoreObject> key = Key.create(id);
return ofy.load(key);
}
#Override
public String getId(DatastoreObject domainObject)
{
if (domainObject.getId() != null)
{
Key<DatastoreObject> key = ofy.fact().getKey(domainObject);
return key.getString();
} else
return null;
}
}
Please note that your implementation may slightly differ because I'm using Objectify4.