I'm using an event system based on the suggestions in this question: Create Custom Event in Java
I implemented it in a component to handle and passthrough the events from a button on the component. I put the component into it's own jar file. Then I used the component and jar file in another project and when I tried to run the program I had created with it, it gave me the following error:
java.lang.IllegalAccessException: Class Eventing.EventHandler can not access a member of class outfit.proto.frmDo$1 with modifiers "public"
This is the code of the EventHandler class I wrote:
public class EventHandler<T> {
private ArrayList<T> listenerPool = new ArrayList<>();
public void addListener(T listener){
listenerPool.add(listener);
}
public void raiseEvent(Object eventData){
for (T listener : listenerPool){
try {
if (eventData != null) {
listener.getClass().getDeclaredMethods()[0].invoke(listener, eventData);
} else {
listener.getClass().getDeclaredMethods()[0].invoke(listener);
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(EventHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
This is how I setup the the EventHandler class on the component:
EventHandler<EventListener> _loginEvent = new EventHandler<>();
public EventHandler<EventListener> loginEvent(){
return _loginEvent;
}
loginButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
_loginEvent.raiseEvent(null);
}
});
This is what I did to catch the events on frmDo:
this.component2.loginEvent().addListener(new EventAdapter() {
#Override
public void executeResult() {
}
});
Based on this wikipedia entry on Observer Patterns I got the event system to work! As I suspected Java has some pre-defined system for these kind of things.
Related
I want to configure separate log directory for every request. Is this possible with helidon?
The oracle helidon JUL examples are located in github. Building off of those examples you would have to create a custom Handler to read the request from the HelidonMdc:
import io.helidon.logging.jul;
import io.helidon.logging.common;
import java.util.logging.*;
public class RequestFileHandler extends Handler {
public RequestFileHandler() {
super.setFormatter(new HelidonFormatter());
}
#Override
public synchronized void publish(LogRecord r) {
if (isLoggable(r)) {
try {
FileHandler h = new FileHandler(fileName(r), Integer.MAX_VALUE, 1, true);
try {
h.setLevel(getLevel());
h.setEncoding(getEncoding());
h.setFilter(null);
h.setFormatter(getFormatter());
h.setErrorManager(getErrorManager());
h.publish(r);
} finally {
h.close();
}
} catch (IOException | SecurityException jm) {
this.reportError(null, jm, ErrorManager.WRITE_FAILURE);
}
}
}
#Override
public void flush() {
}
#Override
public void close() {
super.setLevel(Level.OFF);
}
private String fileName(LogRecord r) {
Optional<String> o = HelidonMdc.get("name");
return o.isPresent() ? o.get() +".log" : "unknown.log";
}}
Like the example code this code is assuming that you have set the value of 'name' to the request id. You would then have to install this handler on your application logger.
I would like to display a progress bar when running a custom IntentionAction in my custom IntellIJ IDEA plugin.
However, it is not displayed no matter what I do. To test whether the problem lies in the IntentionAction, I copy-paste the code to a simple implementation of an AnAction. The whole class looks like so:
public class HelloAction extends AnAction {
public HelloAction() {
super("Hello");
}
public void actionPerformed(AnActionEvent event) {
Project project = event.getData(CommonDataKeys.PROJECT);
ProgressManager.getInstance().run(new Task.Modal(project, "daf", false) {
public void run(ProgressIndicator indicator) {
indicator.setText("This is how you update the indicator");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
indicator.setFraction(0.5); // halfway done
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
}
});
Messages.showMessageDialog(project, "Hello world!", "Greeting", Messages.getInformationIcon());
}
}
And it works perfectly. And when I use the same code inside an IntentionAction, nothing is displayed.
public class GenerateIntentionAction extends PsiElementBaseIntentionAction implements IntentionAction {
...
public void invoke(#NotNull Project project, Editor editor, #NotNull PsiElement element) throws IncorrectOperationException {
ProgressManager.getInstance().run(new Task.Modal(project, "daf", false) {
public void run(ProgressIndicator indicator) {
indicator.setText("This is how you update the indicator");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
indicator.setFraction(0.5); // halfway done
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
}
});
I tried to run call runWithProgressSynchronously instead of run, tried making Task Modal and Backgroundable - to no avail. I do not know what is wrong besides the fact that ProgressIndicator inside IntentionAction is always an EmptyProgressIndicator
If your intention action is invoked inside WriteAction, you can't show modal UI from there. Overriding startInWriteAction and returning false might help.
I would like to fix the issue which is solved in this posting:
Vaadin "A connector with id xy is already registered"
When I add the following code to MyUI I get an error in the getLogger() lline: "The method getLogger() from the type ConnectorTracker is not visible"
public class SomeUI extends UI {
private ConnectorTracker tracker;
#
Override
public ConnectorTracker getConnectorTracker() {
if (this.tracker == null) {
this.tracker = new ConnectorTracker(this) {
#
Override
public void registerConnector(ClientConnector connector) {
try {
super.registerConnector(connector);
} catch (RuntimeException e) {
getLogger().log(Level.SEVERE, "Failed connector: {0}", connector.getClass().getSimpleName());
throw e;
}
}
};
}
return tracker;
}
}
Is there a quick work around for this or any other solution how to fix the xy connector exception?
I am using spring boot with vaadin 7.
The getLogger() method is private, and you are implementing an anonymous subtype, which can only access public and protected methods. You can easily add your own getLogger to your UI subclass:
private static Logger getLogger() {
return Logger.getLogger(SomeUI.class.getName());
}
private ConnectorTracker connectorTracker;
#Override
public ConnectorTracker getConnectorTracker() {
if (connectorTracker == null) {
connectorTracker = new ConnectorTracker(this) {
#Override
public void registerConnector(ClientConnector connector) {
try{
super.registerConnector(connector);
} catch (RuntimeException e) {
getLogger().log(Level.SEVERE, "OOPS!");
throw e;
}
}
};
}
return connectorTracker;
}
To fix the a connector xy is already registered problem you need to check if any of your Components(Views, Layouts, Buttons, Panels, whatever...) are added to a view more than once.
So if a Layout is created with new VerticalLayout() there is no way to reuse it.
Meaning you should check all your Vaadin components and your own Views/UI-Components if they are used twice or if some of them are static.
I have a fully working spring and vaadin application based off spring boot. The application class has now been modified to create a custom servlet so I can use both touchkit and spring within the project as such.
I have been following this git project to perform this:git project example
public class SmartenderApplication {
public static void main(String[] args) {
SpringApplication.run(SmartenderApplication.class, args);
}
#Bean
public VaadinServlet vaadinServlet() {
return new SpringAwareTouchKitServlet();
}}
I modified the custom servlet to follow the vaadin docs for using a UI provider to choose between the touchkit UI and the browswer fallback UI as so
public class SpringAwareTouchKitServlet extends SpringVaadinServlet {
TouchKitSettings touchKitSettings;
MyUIProvider prov = new MyUIProvider();
#Override
protected void servletInitialized() throws ServletException {
super.servletInitialized();
getService().addSessionInitListener(
new SessionInitListener() {
#Override
public void sessionInit(SessionInitEvent event)
throws ServiceException {
event.getSession().addUIProvider(prov);
}
});
touchKitSettings = new TouchKitSettings(getService());
}
}
class MyUIProvider extends UIProvider {
#Override
public Class<? extends UI>
getUIClass(UIClassSelectionEvent event) {
String ua = event.getRequest()
.getHeader("user-agent").toLowerCase();
if ( ua.toLowerCase().contains("ios")) {
return myTouchkitUI.class;
} else {
return myUI.class;
}
}
}
My application works when I do not call this section of code to choose a UI provider. But it will always go to a touchkit UI. :
getService().addSessionInitListener(
new SessionInitListener() {
#Override
public void sessionInit(SessionInitEvent event)
throws ServiceException {
event.getSession().addUIProvider(prov);
}
});
My issue is that although it will choose between which UI class to return as soon as it begins to progress through the chosen UI code it passes back null objects that were originally autowired through spring. Seeing as this works when i dont choose a UI and just goes for touchkit, im assuming it must be somewhere in my UI provider choice code thats stopping the Spring functionality from allowing my classes to autowire, etc?
Well, the UIProvider is supposed to manage UI instances. Furthermore, since you're using Spring (Boot or not) it should retrieve beans from the Spring context instead of creating the instances itself when one is necessary:
UIProvider / DefaultUIProvider:
public UI createInstance(UICreateEvent event) {
try {
return event.getUIClass().newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Could not instantiate UI class", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not access UI class", e);
}
}
Thus, I'd say that instead of extending the simple UIProvider (or rather the DefaultUIProvider) you should extend the SpringUIProvider, which retrieves instances from your app's Spring context, so the automagic will begin to happen again.
SpringUIProvider:
#Override
public UI createInstance(UICreateEvent event) {
final Class<UIID> key = UIID.class;
final UIID identifier = new UIID(event);
CurrentInstance.set(key, identifier);
try {
logger.debug(
"Creating a new UI bean of class [{}] with identifier [{}]",
event.getUIClass().getCanonicalName(), identifier);
return webApplicationContext.getBean(event.getUIClass());
} finally {
CurrentInstance.set(key, null);
}
}
I've implemented Gdxpay into my libgdx game but when I call requestPurchase(), nothing happens. I followed this tutorial https://github.com/libgdx/gdx-pay/wiki/Integration-example-with-resolvers but I'm not sure where I'm going wrong.
Here is the main game class where the purchase observer is:
public MyGame extends Application adapter {
public MyGame(IActivityRequestHandler handler) {
// TODO Auto-generated constructor stub
super();
myRequestHandler = handler;
// ---- IAP: define products ---------------------
purchaseManagerConfig = new PurchaseManagerConfig();
purchaseManagerConfig.addOffer(new Offer().setType(OfferType.ENTITLEMENT).setIdentifier(SKU_REMOVE_ADS));
}
public PurchaseObserver purchaseObserver = new PurchaseObserver() {
#Override
public void handleRestore (Transaction[] transactions) {
for (int i = 0; i < transactions.length; i++) {
if (checkTransaction(transactions[i].getIdentifier()) == true) break;
}
// to make a purchase (results are reported to the observer)
PurchaseSystem.purchase(SKU_REMOVE_ADS);
}
#Override
public void handleRestoreError (Throwable e) {
// getPlatformResolver().showToast("PurchaseObserver: handleRestoreError!");
Gdx.app.log("ERROR", "PurchaseObserver: handleRestoreError!: " + e.getMessage());
throw new GdxRuntimeException(e);
}
#Override
public void handleInstall () {
// getPlatformResolver().showToast("PurchaseObserver: installed successfully...");
Gdx.app.log("handleInstall: ", "successfully..");
}
#Override
public void handleInstallError (Throwable e) {
//getPlatformResolver().showToast("PurchaseObserver: handleInstallError!");
Gdx.app.log("ERROR", "PurchaseObserver: handleInstallError!: " + e.getMessage());
throw new GdxRuntimeException(e);
}
#Override
public void handlePurchase (Transaction transaction) {
checkTransaction(transaction.getIdentifier());
}
#Override
public void handlePurchaseError (Throwable e) {
if (e.getMessage().equals("There has been a Problem with your Internet connection. Please try again later")) {
// this check is needed because user-cancel is a handlePurchaseError too)
// getPlatformResolver().showToast("handlePurchaseError: " + e.getMessage());
}
throw new GdxRuntimeException(e);
}
#Override
public void handlePurchaseCanceled () {
}
};
protected boolean checkTransaction (String ID) {
boolean returnbool = false;
if (SKU_REMOVE_ADS.equals(ID)) {
myRequestHandler.showAds(false);
returnbool = true;
}
return returnbool;
}
public void create() {
...
Here is where requestPurchase is called:
public class MainMenu extends Screen {
#Override
public void update() {
...
if (removeBounds.contains(touchPoint.x, touchPoint.y)) {
MyGame.getPlatformResolver().requestPurchase(MyGame.SKU_REMOVE_ADS);
}
}
...
}
Many thanks.
Edit: Ok logcat says the following error when I request a purchase:
5188-5220/com.comp.myGame.android I/ERRORīš gdx-pay: requestPurchase(): purchaseManager == null
So that means pruchaseManager is null, but according to the tutorial in this instance it should cause the correct purchaseManager to be called so I'm still confused...
I had exactly the same issue. I followed the tutorial as well, but changed the distributed resolver system to a more local defined system where all app store keys are set in the main game class.
This didn't work (with the same error you got). I then re-engineered the code to follow exactly the tutorial - with all the resolver bells and whistles. Next, I got a "no suitable app store found" error while creating the purchaseManager (at this point, I celebrated because it at least TRIED to create it).
I think that it worked the second try has something to do with the sequence flow:
In the android/AndroidLauncher.java, onCreate:
MyGame myGame = new MyGame(this);
initialize(myGame, config);
// init IAP
myGame.setPlatformResolver(new AndroidResolver(myGame, this));
In core/MyGame.java, declarations:
public PurchaseObserver purchaseObserver = new BrainsPurchaseObserver();
public PurchaseManagerConfig purchaseManagerConfig;
In core/MyGame.java, constructor:
purchaseManagerConfig = new PurchaseManagerConfig();
Offer iap15Tipps = new Offer();
iap15Tipps.setIdentifier(Product.brains_hints_15.name());
iap15Tipps.setType(OfferType.CONSUMABLE);
purchaseManagerConfig.addOffer(iap15Tipps);
PlatformResolver.java and AndroidResolver.java as described in the tutorial. This worked to the point of the above error "no app store found".
Then I switched from gdx-pay 0.3.0 to 0.4.0 (by just incrementing the version in the gradle settings, it is already available in the repository), AND IT WORKED!
I suggest you check the sequence of IAP initializing you execute and switch to 0.4.0 if you are not already using it.
-- Michael