I am trying to use akka-quartz-scheduler to trigger a cleanup event at regular intervals. I get the scheduler to send the message to the actor, but only when there is no Calendar associated with the schedule. Whenever I attach a calendar to a schedule, the actor never receives any messages.
This is the application.conf section relevant for akka-quartz-scheduler. If I remove the line
calendars = ["Minimal"]"
from the config, my actor is triggered. If I leave the line in, no actor gets called.
akka {
quartz {
defaultTimezone = "Europe/Oslo"
schedules {
NowAndThen {
description ="Delete temp files now and then, eg every hour"
expression = "*/10 * * * * ?"
calendars = ["Minimal"]
}
}
calendars {
Minimal {
type = Daily
exclude {
startTime = "15:00"
endTime = "15:01"
}
}
}
}
}
I am initializing the extension from a playframework application, in Global.java:
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Extension;
import akka.actor.Props;
import com.typesafe.akka.extension.quartz.QuartzSchedulerExtension;
import play.Application;
import play.GlobalSettings;
import play.Logger;
import play.libs.Akka;
import uttrekk.CleanupRunner;
public class Global extends GlobalSettings {
public void onStart(Application app) {
AkkaStartUp.startup(app);
}
static class AkkaStartUp {
public static void startup(Application app) {
// Starter autoamtiske avelveringer norges eiendommer
ActorSystem system = Akka.system();
ActorRef cleanupRef =system.actorOf(new Props(CleanupRunner.class));
QuartzSchedulerExtension scheduler = (QuartzSchedulerExtension) QuartzSchedulerExtension.get(system);
scheduler.schedule("NowAndThen",cleanupRef,"Clean");
}
}
}
The actor implementation looks something like the following:
package uttrekk;
import akka.actor.UntypedActor;
import play.Logger;
import util.NewProperties;
import java.io.File;
import java.io.FilenameFilter;
public class CleanupRunner extends UntypedActor {
#Override
public void onReceive(Object message) throws Exception {
Logger.info("Running cleanup of temporary files");
}
}
the problem occurs during calendars initialization.
Check line 245 in QuartzSchedulerExtension class:
scheduler.addCalendar(name.toUpperCase, calendar, true, true)
The calendar is added using UpperCase, so Quartz never finds it, producing that no job is triggered then.
If you define your calendar in akka config using UpperCase name it should work.
Related
I use ACRA 5.8.4 and I want to update it to 5.9.6 but #annotations are deprecated and I have to change it to PluginConfigurations, but documentation isn't finished and I don't know how to do it. This is my current Application class:
package com.mycompany.myapp;
import android.app.Application;
import android.content.Context;
import androidx.multidex.MultiDex;
import org.acra.ACRA;
import org.acra.annotation.AcraCore;
import org.acra.annotation.AcraDialog;
import org.acra.annotation.AcraMailSender;
#AcraCore(buildConfigClass = BuildConfig.class)
#AcraMailSender(mailTo = "myemail#mydomain.com",
resSubject = R.string.mailsubject)
#AcraDialog(resTitle = R.string.acratitle,
resText = R.string.acratext,
resPositiveButtonText = R.string.acrasend,
resNegativeButtonText = R.string.acracancel,
resCommentPrompt = R.string.acracomprompt )
public class MyAwsomeApplication extends Application {
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
// The following line triggers the initialization of ACRA
ACRA.init(this);
}
}
And I want to update it to pluginconfigurations:
public class MyAwsomeApplication extends Application {
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
// The following line triggers the initialization of ACRA
CoreConfigurationBuilder builder;
builder = new CoreConfigurationBuilder()
.withBuildConfigClass(BuildConfig.class)
.withReportFormat(StringFormat.JSON)
.withPluginConfigurations(
<-- I think, here I should add new clases for dialog and mail sender -->
);
ACRA.init(this, builder);
}
}
You can use
.withPluginConfigurations(
new DialogConfigurationBuilder()
.withCommentPrompt(getString(R.string.crash_dialog_comment_prompt))
.withText(getString(R.string.crash_dialog_text))
.build(),
new MailSenderConfigurationBuilder()
.withMailTo("crash#report.xx")
.withReportAsFile(true)
.withReportFileName("Crash.txt")
.withBody("getString(R.string.mail_body)")
.build()
)
examples for configuration builders can be found on: https://www.acra.ch/docs/Senders
The question could be summarized: how properly save data to MongoDb throw Spring-data in no-blocking stack using CompletableFuture (i.e. Spring Webflux + reactive.ReactiveCrudRepository + java.util.concurrent)?
I have struglled for the last three days studing and searcing around and reading several tutorials in order to find a recommended way or at least a "north path" to persist data when someone wants to use CompletableFuture for that. I could reach the code bellow succesfully working but I am not sure if I am doing some weird stuff.
Basically, I want to use CompletableFuture because I want to chain futures. Let say, save firstly in MongoDb and if well-done then "thenAcceptAsync" and finally "thenCombine" them.
Well, ReactiveCrudRepository.save returns Mono<> and I must subscribe in order to effectivelly save it. Additionally Mono<>.subscribe() returns dispose whic I understand I can use to cancel it let's say if the thread takes too long because MongoDb is out for instance or any other exception. SO far so good.
What is unclear to me is if I am not messing up the idea of using using saving the data which blocks in assyncronous method. Since my puporse is leave to "future" resolution am I am blocking during the save method bellow and completely losing the benefitis of saving in different thread and get a future result?
Code saving properly to MongoDb but not clear to me if it is really "no-blocking" approach. Note that completableFuture.get() is commented since I don't need it in onder to effectively save my data
#Async("taskExecutor")
public void transferirDisposableReturnedSupplyAsync(Extrato e) throws InterruptedException, ExecutionException {
CompletableFuture<Disposable> completableFuture = CompletableFuture
.supplyAsync(() -> extratoRepository.save(e).subscribe());
//completableFuture.get(); unnecessary since subscribe() above already saved it
}
In case it is relevant:
Repository:
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import com.noblockingcase.demo.model.Extrato;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.data.domain.Pageable;
public interface ExtratoRepository extends ReactiveCrudRepository<Extrato, String> {
#Query("{ id: { $exists: true }}")
Flux<Extrato> retrieveAllExtratosPaged(final Pageable page);
}
AsyncConfiguration:
import java.util.concurrent.Executor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
// The #EnableAsync annotation enables Spring’s ability to run #Async methods in a background thread pool.
// The bean taskExecutor helps to customize the thread executor such as configuring number of threads for an application, queue limit size and so on.
// Spring will specifically look for this bean when the server is started.
// If this bean is not defined, Spring will create SimpleAsyncTaskExecutor by default.
#Configuration
#EnableAsync
public class AsyncConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncConfiguration.class);
#Bean(name = "taskExecutor")
public Executor taskExecutor() {
LOGGER.debug("Creating Async Task Executor");
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("ExtratoThread-");
executor.initialize();
return executor;
}
}
*** added
import { Injectable, NgZone } from '#angular/core';
import { Observable } from 'rxjs';
import { Extrato } from './extrato';
#Injectable({
providedIn: "root"
})
export class SseService {
extratos: Extrato[] = [];
constructor(private _zone: NgZone) { }
getServerSentEvent(url: string): Observable<any> {
this.extratos = [];
return Observable.create(observer => {
const eventSource = this.getEventSource(url);
eventSource.onmessage = event => {
this._zone.run(() => {
let json = JSON.parse(event.data);
this.extratos.push(new Extrato(json['id'], json['description'], json['value'], json['status']));
observer.next(this.extratos);
});
};
eventSource.onerror = (error) => {
if (eventSource.readyState === 0) {
console.log('The stream has been closed by the server.');
eventSource.close();
observer.complete();
} else {
observer.error('EventSource error: ' + error);
}
}
});
}
private getEventSource(url: string): EventSource {
return new EventSource(url);
}
}
I issue I am trying to get rid off is the following:
I intend to setup a costum event handling chain as a workaround for JavaFX's lack of actioncommands.
The issue in particular is, that a menuitem upon clicking it, still fires an ActionEvent instead of the self-written MilvaLabActionEvent.
The code:
Event class
package jpt.gui.items;
import javafx.event.ActionEvent;
public class MilvaLabActionEvent extends ActionEvent {
private static final long serialVersionUID = 6757067652205246280L;
private String actionCommand ="";
public MilvaLabActionEvent(String actionCommand2) {
setActionCommand(actionCommand2);
}
public MilvaLabActionEvent() {}
public String getActionCommand() {
return actionCommand;
}
public void setActionCommand(String actioncommand) {
this.actionCommand = actioncommand;
}
}
My EventHandler:
package jpt.gui.items;
import javafx.event.EventHandler;
import jpt.MilvaLabGlobal;
import jpt.MilvaLabKonst;
import jpt.handle.MilvaLabDateiHandle;
import jpt.handle.MilvaLabEinHandle;
import jpt.handle.MilvaLabHilfeHandle;
import jpt.handle.MilvaLabMilvaHandle;
import jpt.handle.MilvaLabRvAnwendungHandle;
import jpt.handle.MilvaLabrvTextHandle;
import jpt.log4j.MilvaLabLogger;
public class MilvaLabEventHandler implements EventHandler<MilvaLabActionEvent>{
#Override
public void handle(MilvaLabActionEvent event) {
// the command string of the menu item
final String sCmd = event.getActionCommand();
if (sCmd.charAt(0) == 'M')
{//doing something here
}
}
The costum MenuItem-Class I figured out I gotta write.
package jpt.gui.items;
import javafx.event.Event;
import javafx.scene.control.MenuItem;
public class MilvaLabMenuItem extends MenuItem {
private String actionCommand;
public MilvaLabMenuItem(String sText) {
this.setText(sText);
}
#Override
public void fire() {
Event.fireEvent(this, new MilvaLabActionEvent(getActionCommand()));
}
public String getActionCommand() {
return actionCommand;
}
public void setActionCommand(String actionCommand) {
this.actionCommand = actionCommand;
}
}
And the initialization of the costum MenuItem:
final MilvaLabMenuItem jmi = new MilvaLabMenuItem("I am a menuItem");
jmi.addEventHandler(evtype, new MilvaLabEventHandler());
jmi.setOnAction((event) -> {
System.out.print("I have fired an ActionEvent!");
});
Well, as of now, I got "I have fired an ActionEvent" when I click on the MilvaLabMenuItem, nothing else happens. (Looked into that thing already using the debugger).
What I want to happen is that, obviously, the MilvaLabEventHandler is called.
I figured it out again.
I declared two EventTypes, though, only one was necessary.
This helped me finding the solution, though, they use Nodes instead of MenuItems.
How to emit and handle custom events?
I am trying to implement resuable Custom Services without using ext and servicebuilder.
I referred this article: http://www.devatwork.nl/2010/04/implementing-a-reusable-liferay-service-without-ext-or-service-builder/ , but I am confused in how should I implement this using eclipse? Following are the steps that I followed to do this:
- Created liferay-plugin project within eclipse.
- Created package containing CustomServices (interface) and CustomServicesUtil.
- Created jar file of package in step 2.
- Placed that jar file in tomcat\lib\ext\
- Then created package (with in same liferay-plugin project), that includes CutomServicesImpl and CustomServicesBaseImpl
- Defined portlet-spring.xml, service.properties, and modified web.xml (as per the article), and finally deployed the project.
On deployment, project is deployed successfully, but when I am trying to use customMethods defined in CustomServicesImpl through CustomServicesUtil.getCustomMethod(), I am getting the following error:
"java.lang.ClassNotFoundException: com.demo.custom.services.CustomServicesUtil"
I configure build path to include customservices.jar file but its not working out, still showing the same error. I don’t know whether this is the correct way to implement resuable services or not. I tried this so that i can make use of custom method in one of my project.
Here is the code for custom services:
CustomServices.java
package com.demo.custom.services;
import com.liferay.portal.model.User;
public interface CustomServices {
String getCustomName(User user);
}
CustomServicesUtil.java
package com.demo.custom.services;
import com.liferay.portal.model.User;
public class CustomServicesUtil {
private static CustomServices services;
public static CustomServices getServices() {
if (services == null) {
throw new RuntimeException("Custom Services not set");
}
return services;
}
public void setServices(CustomServices pServices) {
services = pServices;
}
public static String getCustomName(User user){
return getServices().getCustomName(user);
}
}
CustomServicesBaseImpl.java
package com.demo.custom.services.impl;
import com.demo.custom.services.CustomServices;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.service.base.PrincipalBean;
import com.liferay.portal.util.PortalUtil;
public abstract class CustomServicesBaseImpl extends PrincipalBean implements CustomServices {
protected CustomServices services;
public CustomServices getServices() {
return services;
}
public void setServices(CustomServices pServices) {
this.services = pServices;
}
protected void runSQL(String sql) throws SystemException {
try {
PortalUtil.runSQL(sql);
} catch (Exception e) {
throw new SystemException(e);
}
}
}
CustomServicesImpl.java
package com.demo.custom.services.impl;
import com.liferay.portal.model.User;
public class CustomServicesImpl extends CustomServicesBaseImpl {
#Override
public String getCustomName(User user) {
// TODO Auto-generated method stub
if(user == null){
return null;
}else{
return new StringBuffer().append(user.getFirstName()).append(" ").append(user.getLastName()).toString();
}
}
}
Here is the code of controller class of my another portlet, where i am making use of this service.
HelloCustomName.java
package com.test;
import java.io.IOException;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.demo.custom.services.CustomServicesUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.User;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class HelloCustomName extends MVCPortlet {
#Override
public void doView(RenderRequest renderRequest,
RenderResponse renderResponse) throws IOException, PortletException {
System.out.println("--doview----");
ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
User user = themeDisplay.getUser();
String customName = CustomServicesUtil.getCustomName(user); //getting error here
System.out.println("customName:" + customName);
}
}
Please point me on how to implement resuable services? Any guidance will be really useful.
Thanks.
My mind, you don't need the complexity of services. Simply make utility classes and put this in to tomcat/lib/ext. Be sure that tomcat/lib/ext is correct configured in tomcat/conf/catalina.properties, something like this:
common.loader=${catalina.home}/lib/ext/*.jar
I'm using a daemon-script which is monitoring a remote server. When the remote server is up, i want that Netbeans automatically connects it's Debugger to the remote Server.
Is it possible to control this behavior from commandline?
To type Something like
netbeans --attach-debugger 192.168.178.34:9009
inside a terminal to do that? Or what other ways do i have to get access to Netbeans-internal stuff? (until now, i was just a "user" of Netbeans so i don't know the internals and how to access them very well)
Or will i have to write a Netbeans Plugin to do that? If yes, can you give me a good starting point to add that functionality?
Ok since there is no option to attach the Debugger from commandline, i wrote a Netbeans Plugin with the help of this blog entry and this thread from the NB-mailinglist. Now i'm able to call my plugin actions from the Commandline.
So build a simple NetBeans Module, which contains 2 important classes.
This is the class which gets the commandline parameters and forwards them to my Action:
import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.swing.Action;
import org.netbeans.api.sendopts.CommandException;
import org.netbeans.spi.sendopts.Env;
import org.netbeans.spi.sendopts.OptionProcessor;
import org.netbeans.spi.sendopts.Option;
import org.openide.ErrorManager;
import org.openide.cookies.InstanceCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager;
#ServiceProvider(service = OptionProcessor.class)
public class TriggerActionCommandLine extends OptionProcessor {
//Here we specify "runAction" as the new key in the command,
//but it could be any other string you like, of course:
private static Option action = Option.requiredArgument(Option.NO_SHORT_NAME, "debug");
private static final Logger logger = Logger.getLogger(AttachDebugger.class.getName());
#Override
public Set<org.netbeans.spi.sendopts.Option> getOptions() {
return Collections.singleton(action);
}
#Override
protected void process(Env env, Map<Option, String[]> values) throws CommandException {
final String[] args = (String[]) values.get(action);
if (args.length > 0) {
//Set the value to be the first argument from the command line,
//i.e., this is "GreetAction", for example:
final String ip = args[0];
//Wait until the UI is constructed,
//otherwise you will fail to retrieve your action:
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
#Override
public void run() {
//Then find & perform the action:
Action a = findAction(AttachDebugger.ACTION_NAME);
// forward IP address to Action
ActionEvent e = new ActionEvent(this, 1, ip);
a.actionPerformed(e);
}
});
}
}
public Action findAction(String actionName) {
FileObject myActionsFolder = FileUtil.getConfigFile("Actions/PSFActions");
FileObject[] myActionsFolderKids = myActionsFolder.getChildren();
for (FileObject fileObject : myActionsFolderKids) {
logger.info(fileObject.getName());
//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 is my Plugin Action which attaches the Debugger to the given remote address:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.debugger.jpda.DebuggerStartException;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionRegistration;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionID;
import org.python.util.PythonInterpreter;
#ActionID(category = "PSFActions", id = "de.mackaz.AttachDebugger")
#ActionRegistration(displayName = "#CTL_AttachDebuggerAction")
#ActionReferences({
#ActionReference(path = "Menu/Tools", position = 1800, separatorBefore = 1750, separatorAfter = 1850)
})
public final class AttachDebugger implements ActionListener {
private static final Logger logger = Logger.getLogger(AttachDebugger.class.getName());
public static final String ACTION_NAME="AttachDebugger";
#Override
public void actionPerformed(ActionEvent e) {
String ip;
if (!e.getActionCommand().contains("Attach Debugger")) {
ip = e.getActionCommand();
} else {
ip = lookupIP();
}
try {
logger.log(Level.INFO, "Attaching Debugger to IP {0}", ip);
JPDADebugger.attach(
ip,
9009,
new Object[]{null});
} catch (DebuggerStartException ex) {
int msgType = NotifyDescriptor.ERROR_MESSAGE;
String msg = "Failed to connect debugger to remote IP " + ip;
NotifyDescriptor errorDescriptor = new NotifyDescriptor.Message(msg, msgType);
DialogDisplayer.getDefault().notify(errorDescriptor);
}
}
}
Now i can attach the Netbeans debugger to a specific address by calling netbeans/bin/netbeans --debug 192.168.178.79