I have an Eclipse RCP application which I am migrating from Eclipse 3.0 to 4.4, which works fine so far. Due to the migration, some menue entries (e.g. generic open file) were added, which I want to remove. This works so far, because I am calling hideActionset(...) in my perspectiveActivated() methods.
The menu entries disappear. But when I reset the perspective and then change the perspective, the menu entries appear again. I tried to fix this by calling hideActionSet(...) in my perspectiveChanged(...) methods, but they get called so often that I get a stackoverflow.
/**
* #see org.eclipse.ui.IPerspectiveListener#perspectiveActivated(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor)
*/
public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective)
{
if( perspective.getId().equals(m_PerspektivenID) || m_PerspektivenID.equals(STANDARDAKTION))
{
setEnabled( true );
}
else
{
setEnabled( false );
}
if(page != null)
{
page.hideActionSet("org.eclipse.ui.actionSet.keyBindings");
page.hideActionSet("org.eclipse.ui.actionSet.openFiles");
}
}
/**
* #see org.eclipse.ui.IPerspectiveListener#perspectiveChanged(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor, java.lang.String)
*/
public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId)
{
if(page != null)
{
page.hideActionSet("org.eclipse.ui.actionSet.keyBindings");
page.hideActionSet("org.eclipse.ui.actionSet.openFiles");
}
}
Here's a snipped of one of the two log-files that are being generated:
!ENTRY org.eclipse.equinox.event 4 0 2016-01-12 14:37:00.768
!MESSAGE Exception while dispatching event org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET] to handler org.eclipse.e4.ui.services.internal.events.UIEventHandler#faec277
!STACK 0
java.lang.StackOverflowError
at java.util.HashMap.hash(HashMap.java:338)
at java.util.HashMap.containsKey(HashMap.java:595)
at java.util.Collections$SynchronizedMap.containsKey(Collections.java:2578)
at org.eclipse.e4.core.internal.contexts.EclipseContext.set(EclipseContext.java:347)
at org.eclipse.e4.ui.internal.services.ContextContextService.setEventCaching(ContextContextService.java:129)
at org.eclipse.e4.ui.internal.services.ContextContextService.deferUpdates(ContextContextService.java:86)
at org.eclipse.ui.internal.contexts.ContextService.deferUpdates(ContextService.java:92)
at org.eclipse.ui.internal.Perspective.removeActionSet(Perspective.java:362)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2593)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:867)
at org.eclipse.ui.internal.PerspectiveListenerList.fireEvent(PerspectiveListenerList.java:58)
at org.eclipse.ui.internal.PerspectiveListenerList.firePerspectiveChanged(PerspectiveListenerList.java:131)
at org.eclipse.ui.internal.WorkbenchWindow.firePerspectiveChanged(WorkbenchWindow.java:1721)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2596)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:867)
at org.eclipse.ui.internal.PerspectiveListenerList.fireEvent(PerspectiveListenerList.java:58)
at org.eclipse.ui.internal.PerspectiveListenerList.firePerspectiveChanged(PerspectiveListenerList.java:131)
at org.eclipse.ui.internal.WorkbenchWindow.firePerspectiveChanged(WorkbenchWindow.java:1721)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2596)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:867)
at org.eclipse.ui.internal.PerspectiveListenerList.fireEvent(PerspectiveListenerList.java:58)
at org.eclipse.ui.internal.PerspectiveListenerList.firePerspectiveChanged(PerspectiveListenerList.java:131)
at org.eclipse.ui.internal.WorkbenchWindow.firePerspectiveChanged(WorkbenchWindow.java:1721)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2596)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
If you look at the stack trace you can clearly see that when you call WorkbenchPage.hideActionSet a new perspective changed event is being fired and perspectiveChanged is being called again while you are still in the first perspectiveChanged call.
One way to stop this is to have a flag in your perspectiveChanged method to detect that you are already dealing with a change.
Something like:
private boolean changeActive;
public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId)
{
if (changeActive) { // Don't do anything if already handling change
return;
}
changeActive = true;
if (page != null)
{
page.hideActionSet("org.eclipse.ui.actionSet.keyBindings");
page.hideActionSet("org.eclipse.ui.actionSet.openFiles");
}
changeActive = false;
}
Related
I am getting an error when using a LogEventListener.
When I just print something, for example in the beforeEvent method, everything is fine, but when I set any action in any method, I get this error:
java.lang.StackOverflowError
at java.base/java.lang.String.replace(String.java:2173)
at com.codeborne.selenide.impl.SelenideElementDescriber.selector(SelenideElementDescriber.java:67)
at com.codeborne.selenide.impl.ElementFinder.elementCriteria(ElementFinder.java:137)
at com.codeborne.selenide.impl.ElementFinder.getSearchCriteria(ElementFinder.java:130)
at com.codeborne.selenide.impl.Alias$NoneAlias.getOrElse(Alias.java:43)
at com.codeborne.selenide.impl.WebElementSource.description(WebElementSource.java:60)
at com.codeborne.selenide.impl.SelenideElementProxy.invoke(SelenideElementProxy.java:81)
at jdk.proxy2/jdk.proxy2.$Proxy17.is(Unknown Source)
at com.bme.listeners.EventLogger.beforeEvent(EventLogger.java:16)
at com.codeborne.selenide.logevents.SelenideLogger.beginStep(SelenideLogger.java:121)
at com.codeborne.selenide.logevents.SelenideLogger.beginStep(SelenideLogger.java:57)
at com.codeborne.selenide.impl.SelenideElementProxy.invoke(SelenideElementProxy.java:81)**
Code:
public class EventLogger implements LogEventListener {
#Override
public void beforeEvent(LogEvent log) {
if(Selenide.$("path").is(visible)) {
System.out.println("Before Event");
}
}
#Override
public void afterEvent(LogEvent log) {
}
}
Can anyone help me understand?
My best guess as to the cause of this problem is that calling Selenide.$("path").is(visible) causes a log event to be generated. This would cause your listener gets called again, so Selenide.$("path").is(visible) gets called again, which causes another log event, so your listener gets called again, and so on and so on until the stack overflows. However, I don't have enough of your stacktrace to be sure. I would be more sure of this problem if you could include the stacktrace down as far as the second line in which com.bme.listeners.EventLogger.beforeEvent appears.
What might help is adding a boolean field to your listener that records whether it is currently logging an event, and does nothing if beforeEvent is called and this field is true:
public class EventLogger implements LogEventListener {
private boolean isCurrentlyLoggingAnEvent = false;
#Override
public void beforeEvent(LogEvent log) {
if (isCurrentlyLoggingAnEvent) {
// Prevent recursive call.
return;
}
isCurrentlyLoggingAnEvent = true;
try {
if(Selenide.$("path").is(visible)) {
System.out.println("Before Event");
}
}
finally {
isCurrentlyLoggingAnEvent = false;
}
}
#Override
public void afterEvent(LogEvent log) {
}
}
I've used a try-finally block to ensure that the field isCurrentlyLoggingAnEvent is always set back to false, even when an exception is thrown from within the try block.
If you plan to put any logic in afterEvent, you may want to consider doing something similar there.
Context
I'm building a Flutter Plugin above the DJK SDK. For that, I have to implement the communication with the aircraft on the native side, and I'm doing it with Java. I'm also doing it only for Android.
One of the methods of the API is boolean connectToAircraft(), which must return if the connection with the aircraft succeeded.
Expected/current behavior
After I call connectToAircraft() - which invokes the DJISDKManager.getInstance().startConnectionToProduct() method, I expected to be able to use anything related to aircraft immediately, but this doesn't happen. I have to wait a few seconds before I can retrieve data from the aircraft.
Some code
public class UavApi implements IUavApi, DJISDKManager.SDKManagerCallback {
...
private final CountDownLatch onConnectToUavFinishedSignal = new CountDownLatch(1);
...
public boolean connectToUav() throws InterruptedException {
Logger.v("connectToUav()");
DJISDKManager.getInstance().startConnectionToProduct();
synchronized (onConnectToUavFinishedSignal) {
onConnectToUavFinishedSignal.await();
}
return DJISDKManager.getInstance().getProduct() instanceof Aircraft;
}
...
#Override
public void onProductConnect(#Nullable final BaseProduct baseProduct) {
Logger.v(MessageFormat.format("onProductConnect(product: {0})", baseProduct));
if (baseProduct != null) {
handleProductConnected(baseProduct);
}
}
#Override
public void onProductChanged(#Nullable final BaseProduct baseProduct) {
Logger.v(MessageFormat.format("onProductChanged(product: {0})", baseProduct));
if (baseProduct != null) {
handleProductConnected(baseProduct);
}
}
...
private void handleProductConnected(#NonNull final BaseProduct baseProduct) {
Logger.d(MessageFormat.format("Is null? {0}", baseProduct == null ? "Yes" : "No"));
Logger.d(MessageFormat.format("Type: {0}", baseProduct.getClass().getSimpleName()));
onConnectToUavFinishedSignal.countDown();
}
...
}
Problem
The code above is what I tried to do, but it's not working and guess it's because I'm misunderstanding the use of the onProductChange() and onProductConnect() methods.
The DJISDKManager.getInstance().getProduct() is always returning null.
OBS: It's always returning null immediately after the onConnectToUavFinishedSignal.await() call finishes. After a few seconds, I get a valid instance of the aircraft.
Something I've also noticed is that sometimes the onProductChange() is called with some value that the log outputs as Unknwoun and None. What are those and how can I test for them? Like if (baseProduct == ???) doSomething()
Environment
Android 9
MSDK 4.13.1
Phantom 4 Pro
Difference
According to the SDK Docs onProductChanged is primarily used to detect when the connection status changes from only remote controller connected to a full connection between the aircraft and the SDK running on your device.
Keep in mind that when the aircraft is disconnected, this method will be called with an instance of an aircraft, but this instance will come with property isConnected as false. If you print the aircraft object to the console you will notice that if isConnected is true, it will print the aircraft name, otherwise, it will print "None".
As long for the onProductConnect, it will be called always after DJISDKManager.getInstance().registerApp() succeeded or after you manually connect to the aircraft with success using DJISDKManager.getInstance().startConnectionToProduct(). In my tests, even though the app registration succeeds, the method will return false, so you might need to check if the SDKManagerCallback::onRegister results in DJISDKError.REGISTRATION_SUCCESS.
Solution
You need to listen to component change events. Unfortunately just because the product is connected it does not mean that the individual components, such as the flight controller, camera etc are connected. You will need to implement onComponentChange and add a listener to detect when a component is connected. These don't always connect in the same order and may start to connect before or after the product is connected.
#Override
public void onComponentChange(
BaseProduct.ComponentKey componentKey,
BaseComponent oldBaseComponent,
BaseComponent newBaseComponent
) {
newBaseComponent.setComponentListener(isConnected -> {
// check if component connected and access data
if (isConnected) {
if(componentKey == ComponentKey.FLIGHT_CONTROLLER) {
// DJISDKManager.getInstance().getProduct() should no longer be null
DJISDKManager.getInstance().getProduct().getModel();
}
}
})
}
I'm trying to implement in-app purchase in my latest android project.
To do so, I'm following this guide.
Everything went smooth until I used the dispose method in order to close any communication with the play store.
What I get is the following error:
Error:(101, 45) error: unreported exception IabAsyncInProgressException; must be caught or declared to be thrown
On the following code segment:
#Override
public void onDestroy() {
super.onDestroy();
//Always unbind the with the store connection, otherwise performance degradation of the device may follow.
if (mHelper != null) mHelper.dispose();
mHelper = null;
}
After digging in the IabHelper class (Java) I found the dispose method.
Here the code of the method:
/**
* Dispose of object, releasing resources. It's very important to call this
* method when you are done with this object. It will release any resources
* used by it such as service connections. Naturally, once the object is
* disposed of, it can't be used again.
*/
public void dispose() throws IabAsyncInProgressException {
synchronized (mAsyncInProgressLock) {
if (mAsyncInProgress) {
throw new IabAsyncInProgressException("Can't dispose because an async operation " +
"(" + mAsyncOperation + ") is in progress.");
}
}
logDebug("Disposing.");
mSetupDone = false;
if (mServiceConn != null) {
logDebug("Unbinding from service.");
if (mContext != null) mContext.unbindService(mServiceConn);
}
mDisposed = true;
mContext = null;
mServiceConn = null;
mService = null;
mPurchaseListener = null;
}
What should I do to resolve this error?
I understand that I should catch and exception but I am not confident enough to change by myself this method in this class.
(Thanks for any help)
After more research I've found that this question was already asked and answered.
Unfortunately the question is still marked as not answered.
Here there is the link to the original question.
The solution is simple:
The file that you can get from the guide are outdated, and should be instead downloaded from github.
In the method onDestroy you should instead use the following code:
#Override
public void onDestroy() {
super.onDestroy();
//Always unbind the connection with the store, otherwise performance degradation of the device may follow.
if (mHelper != null) {
mHelper.disposeWhenFinished();
mHelper = null;
}
}
disposeWhenFinished it's a more elegant solution that works better than a dispose.
I have spent almost three days trying to do a simple enable / disable of Actions in the netbeans plaform, something that I though was going to be simple, and should be a common feature is more complex than I thought.
At the begging I tried to see if there was an setEnable() method on the default actions generated and to my surprise there is not. Then I started looking into that and I found that most common method to do it was setting a conditionally enabled action (which depends on a Cookie class), So I figured out how to add a fake class to the Lookup so it gets enabled and disabled, I did it the following way. To test it out I added the following code to another action which should enable or disable the second one.
private final PlottingStarted plottingStarted = new PlottingStarted();
#Override
public void actionPerformed(ActionEvent e) {
// TODO implement action body
if (Lookup.getDefault().lookup(PlottingStarted.class) == null) {
ic.add(plottingStarted);
}else{
ic.remove(plottingStarted);
}
So PlottingStarted is a fake object I created which only purpose is being in the lookup to disable or enable the action.
For some reason it did not do anything at all an the Action was always disabled. I tried many things and finally I gave up.
Then I tried a different approach and was using AbstractActions which do have the setEnabled() ability.
To retrieve the action I based myself on one the Geertjan blogs and I created the following method
public Action findAction(String actionName) {
FileObject myActionsFolder = FileUtil.getConfigFile("Actions/RealTimeViewer");
if (myActionsFolder != null){
FileObject[] myActionsFolderKids = myActionsFolder.getChildren();
for (FileObject fileObject : myActionsFolderKids) {
//Probably want to make this more robust,
//but the point is that here we find a particular Action:
if (fileObject.getName().contains(actionName)) {
try {
DataObject dob = DataObject.find(fileObject);
InstanceCookie ic = dob.getLookup().lookup(InstanceCookie.class);
if (ic != null) {
Object instance = ic.instanceCreate();
if (instance instanceof Action) {
Action a = (Action) instance;
return a;
}
}
} catch (Exception e) {
ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
return null;
}
}
}
}
return null;
}
This method worked perfectly and I was able to retrieve the action and call its setEnabled() method. Unfortunately no matter why I did the Action was always enabled.
Reading some literature I found that I should add the following to the registration of the action "lazy = false" and finally I was able to enable and disable the Action... But off course the default registration is lost and I have no Icons and Names.
Now I decided to post again because I cannot believe that it need to be that complex, there must be a way to do it easier. The only thing I need is to have a PLAY / STOP functionality, when PLAY is enabled STOP is disabled and vice-versa.
I have not done this myself but it seems to be covered in Chapter 5.1.2.1 "Complex Enablement" of the book "Netbeans Platform for Beginners". https://leanpub.com/nbp4beginners
The book is not free but the corresponding code sample is available on
github. https://github.com/walternyland/nbp4beginners/tree/master/chapters/ch05/5.1.2.1 He extends AbstractAction overrides the resultChanged method and uses super.setEnabled().
#ActionID(id = "org.carsales.evaluator.EvaluateCarAction1", category = "Car")
#ActionRegistration(displayName = "not-used", lazy = false)
public class EvaluateCarAction extends AbstractAction
implements ContextAwareAction, LookupListener {
// ...
#Override
public void resultChanged(LookupEvent le) {
//Optionally, check if the property is set to the value you're interested in
//prior to enabling the Action.
super.setEnabled(result.allInstances().size() > 0);
}
Thanks to everybody for your responses. I finally got it to work by extending AbstractAction, it seems that even if you register "lazy = false" some of the registration is still being done by the platform and you just need some minor tweaking in the Action constructor. The final result was
#ActionID(
category = "RealTimeViewer",
id = "main.java.com.graph.actions.StopPlotting"
)
#ActionRegistration(
//iconBase = "main/java/com/graph/images/stop-plotting-24x24.png",
displayName = "#CTL_StopPlotting",
lazy = false
)
#ActionReference(path = "Toolbars/RealTimeViewer", position = 600)
#Messages("CTL_StopPlotting=Stop Plotting")
public final class StopPlotting extends AbstractAction{
private static final String ICON = "main/java/com/dacsys/cna/core/graph/images/stop-plotting-24x24.png";
public StopPlotting() {
putValue(SMALL_ICON, ImageUtilities.loadImageIcon(ICON, false));
putValue(NAME, Bundle.CTL_StopPlotting());
this.setEnabled(false);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO implement action body
Action a = new ActionsHelper().findAction("StartPlotting");
if (a != null){
if (a != null){
if (a.isEnabled()){
a.setEnabled(false);
this.setEnabled(true);
}else{
a.setEnabled(true);
this.setEnabled(false);
}
}
}
}
}
I'm facing NullPointer exception on click on a button in GWT, Could someone suggest me how to go ahead and debug the issue ? I have posted the snippet of the code here.
I have a form which creates a movie ticket on create, cancel if user decides not to. On cancel it loads back to the first form successfully but parent form buttons throw null pointer exception on click.
Note: These parent buttons were works just fine if i don't load createMovie page.
createMovie.class
public void init( ClickListener listener )
{
// code ...
// ........
cancel.addClickListener( listener );
createMovie.add( header );
createMovie.add( table );
createMovie.setHeight( "663px" );
initWidget( createMovie );
}
In FocusWidget.class
public void addClickListener(ClickListener listener) {
if (clickListeners == null) {
clickListeners = new ClickListenerCollection();
sinkEvents(Event.ONCLICK);
}
clickListeners.add(listener);
}
// code
#Override
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONCLICK:
if (clickListeners != null) {
clickListeners.fireClick(this); ------->>> LINE 102
}
break;
case Event.ONBLUR:
case Event.ONFOCUS:
if (focusListeners != null) {
focusListeners.fireFocusEvent(this, event);
}
break;
case Event.ONKEYDOWN:
case Event.ONKEYUP:
case Event.ONKEYPRESS:
if (keyboardListeners != null) {
keyboardListeners.fireKeyboardEvent(this, event);
}
break;
}
}
In ClickListenerCollection.class
public void fireClick(Widget sender) {
for (ClickListener listener : this) {
listener.onClick(sender);
}
}
Errors:
[ERROR] Uncaught exception escaped
java.lang.NullPointerException: null
at com.google.gwt.user.client.ui.ClickListenerCollection.fireClick(ClickListenerCollection.java:34)
at com.google.gwt.user.client.ui.FocusWidget.onBrowserEvent(FocusWidget.java:102)
at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1308)
at com.google.gwt.user.client.DOM.dispatchEventAndCatch(DOM.java:1287)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1255)
at sun.reflect.GeneratedMethodAccessor34.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
A NullPointerException means that you're trying to run something on a null object. (Well, not exactly, but that's basically it.)
First of all, learn how to read a stack trace. It's a very important skill. Basically, go down the stack until you find a file that is yours. In this case, it's FocusWidget:102. Since I don't know which line 102 is, I'll just guess.
Since you seem to be implying that the error is in that code snippet, and anything in the if statement can't be null since you're checking for it, my guess is that somehow the argument "listener" is null. I'm not sure, though. It'd be helpful if you could give us the entire block of code that's causing the issue, i.e. the scope around line 102.
Things i have done to fix,
I had cancel button in both forms (parent & child) and upon calling 'cancel' in createMovie.class ( child ) i was removing the parent form. So when i attempted to press 'cancel' in child form ( createMovie ) the listener was passing Null.
Fix
if ( childFormLoaded )
{
if ( panelsControl.containsPanel( createMovie.class.getName() ) )
panelsControl.removePanel( createMovie.class.getName() );
}
else
{
if ( panelsControl.containsPanel( ParentClass.class.getName() ) )
panelsControl.removePanel( ParentClass.class.getName() );
}