How to create a cron job in Play Framework - java

I'm creating a simple cron job that run a task in a specific time (for example 3AM) with Play Framework 2.6.x.
But now I'm stucking in a simple schedule task:
I created an Actor:
package actors;
import akka.actor.UntypedActor;
import org.slf4j.LoggerFactory;
public class DoSomethingActor extends UntypedActor {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(DoSomethingActor.class);
#Override
public void onReceive(final Object message) throws Throwable {
log.info("Write your crone task or simply call your method here that perform your task " + message);
}
}
Then I created a Schedule class that call Actor each time I've set:
package tasks;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Cancellable;
import scala.concurrent.duration.Duration;
#Singleton
public class DoSomethingScheduler {
#Inject
public DoSomethingScheduler(final ActorSystem system,
#Named("do-something-actor") final ActorRef doSomethingActor) {
final Cancellable scheduler;
final int timeDelayFromAppStart = 0;
final int timeGapInSeconds = 1; //Here you provide the time delay for every run
system.scheduler().schedule(
Duration.create(timeDelayFromAppStart, TimeUnit.MILLISECONDS), //Initial delay when system start
Duration.create(timeGapInSeconds, TimeUnit.SECONDS), //Frequency delay for next run
doSomethingActor,
"message for onreceive method of doSomethingActor",
system.dispatcher(),
null);
}
}
Finally, I bind these class in a Module class:
package modules;
import actors.DoSomethingActor;
import com.google.inject.AbstractModule;
import play.libs.akka.AkkaGuiceSupport;
import tasks.DoSomethingScheduler;
public class SchedulerModule extends AbstractModule implements AkkaGuiceSupport{
#Override
protected void configure() {
this.bindActor(DoSomethingActor.class, "do-something-actor");
this.bind(DoSomethingScheduler.class).asEagerSingleton();
}
}
After these things, I run the application but it doesn't work as I expected. I expected it shows a logging every 1 SECOND but there is nothing happen.
Could you please help me to fix it?
Thank you so much!

The solution is in dev mode, I have to send a HTTP request to the application to load the module. In production mode, they will be loaded immediately.

Related

Cannot make a static reference to the non-static method --- from the type --- Java Bukkit Minecraft

I know there have been plenty of other posts like this from people trying to find their problem in their static class and I have read them but to no avail. I am trying to make a minecraft bukkit plugin for bedwars and when trying to use world.--- I constantly get these errors(Cannot make a static reference to the non-static method getPlayers from the type World) and cannot find where the static class is originating from. Here is my code:
package me.fitch.bedwars.timers;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.World;
import org.bukkit.entity.Player;
import me.fitch.bedwars.main;
public class starttimer implements Listener {
private main plugin;
public starttimer(main plugin) {
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
#EventHandler
public void startjoin(PlayerJoinEvent e)
{
Object [] players = World.getPlayers().toArray(); //error here
if(players.length == 8)
{
//start countdown
}
}
}
Hope you can help and that I'm not just blind
Thanks :)
Edit: after instantiating World server = new World(); I am now getting "Cannot instantiate the type World" errors, thanks for the help so far guys, hope you can help with this :)
Edit 2: so e.getPlayer().getWorld() works now so thanks but I'm now having issues in my main class where e is not a thing
package me.fitch.bedwars;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.plugin.java.JavaPlugin;
import me.fitch.bedwars.listeners.beddestroy;
public class main extends JavaPlugin {
private main plugin;
public main(main plugin) {
this.plugin = plugin;
}
#Override
public void onEnable()
{
World.setSpawnLocation(Integer.parseInt( plugin.getConfig().getString("respawn_pointx")), Integer.parseInt( plugin.getConfig().getString("respawn_pointx")) + 1,Integer.parseInt( plugin.getConfig().getString("respawn_pointz")));
new beddestroy(this);
}
}
You will want your listener in its own class myListener.java.
From within the listener events in that class you should be able to do everything you need to do.
I like to create a public static Plugin object in case you ever need to reference the specific instance of the Plugin object from any other class in your plugin.
You will register the listener like this in Main.onEnable()
package myPlugin;
import myPlugin.myListenerClass;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin {
public static Plugin instance;
#Override
public void onEnable() {
instance = this;
PluginManager my_pm = getServer().getPluginManager();
my_pm.registerEvents(new myListenerClass(), this);
}
}
Your myListenerClass.java will be setup something like the following:
package myPlugin;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
public class myListenerClass implements Listener {
#EventHandler
public void onJoin(PlayerJoinEvent event) {
System.out.println("PlayerJoinEvent was triggered!");
int playerCount = Bukkit.getServer().getOnlinePlayers().size();
if (playerCount == 8) {
// start countdown
}
}
}

How to create a background job in AEM as a Cloud?

I want to create a daily background job to be executed by AEM.
I read an aem document and apache sling official site, and I thought I need two classes.
a service class that register the job to JobManager.
a consumer class that do the job.
So I tried these code, but my job was not executed.
service class
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.JobBuilder.ScheduleBuilder;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Component
public class MyJobService {
private static final Logger logger = LoggerFactory.getLogger(MyJobService.class);
#Reference
private JobManager jobManager;
public static final String JOB_TOPIC = "my/sample/jobtopic";
public void startScheduledJob() {
ScheduleBuilder scheduleBuilder = jobManager.createJob(JOB_TOPIC).schedule();
scheduleBuilder.hourly(9, 0); // execute daily at AM9:00
if (scheduleBuilder.add() == null) {
logger.error("myjobservice error");
}
}
}
job consumer class
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Component(
immediate = true,
service = JobConsumer.class,
property = {
JobConsumer.PROPERTY_TOPICS + "=my/sample/jobtopic"
}
)
public class MyJobConsumer implements JobConsumer {
private static final Logger logger = LoggerFactory.getLogger(MyJobConsumer.class);
#Override
public JobResult process(Job job) {
String topic = job.getTopic();
logger.info("this message is from myjobconsumer. topic is " + topic);
return JobResult.OK;
}
}
Do I need another class or some configurations? Does My code have something wrong?
If you annotate a method with #Activate it will be called when the component starts.
#Activate
public void startScheduledJob()
I guess you want your job to run on startup.
Another option would be to let MyJobService be a servlet and call it from outside.

How to retrieve the Application Context in Spring Boot 2

I have this ApplicationContextProvider class defined along with the MyApplication.java (entry point where the application is run):
package com.company.my.app;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
#Component
public class ApplicationContextProvider implements ApplicationContextAware {
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getContext() {
return applicationContext;
}
}
Have the package restapi with two classes in it (Greeting is just a class to hold data):
package com.company.my.app.restapi;
import com.company.my.app.ApplicationContextProvider;
import io.micrometer.core.instrument.Counter;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class GreetingController {
private static final Logger LOG = LoggerFactory.getLogger(GreetingController.class);
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
ApplicationContextProvider acp = new ApplicationContextProvider();
ApplicationContext context = acp.getContext();
if (context == null) LOG.info("app context is NULL");
Counter bean = context.getBean(Counter.class);
bean.increment();
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
Finally the MyApplication class is:
package com.company.my.app;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.binder.MeterBinder;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Counter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#SpringBootApplication
public class MyApplication {
#Bean
public MeterBinder exampleMeterBinder() {
return (meterRegistry) -> Counter.builder("my.counter")
.description("my simple counter")
.register(meterRegistry);
}
#Configuration
public class CounterConfig {
#Bean
public Counter simpleCounter(MeterRegistry registry) {
return registry.counter("my.counter");
}
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
When I run the app and call http://localhost:8081/greeting in my browser, it crashes printing app context is NULL. How do I get the application context? I need it to retrieve the simple counter bean.
tl;dr: You don't need the context; there's a better way.
ApplicationContextAware is an artifact from much older versions of Spring, before many of the now-standard features were available. In modern Spring, if you need the ApplicationContext, just inject it like any other bean. However, you almost certainly shouldn't interact with it directly, especially for getBean, which should be replaced with injecting whatever you were getting.
In general, when you need a Spring bean, you should declare it as a constructor parameter. (If you have multiple constructors, you need to annotate one with #Autowired, but if there's only a single constructor, Spring is smart enough to know to use it.) If you're using Lombok, you can use #Value to automatically write the constructor, and Groovy and Kotlin have similar features.
In the specific case of Micrometer, which you're showing here, it is not conventional to declare individual metrics as beans because they are fine-grained tools intended to apply to specific code paths. (Some services might have 10 separate metrics to track various possible scenarios.) Instead, you inject the MeterRegistry and select the counters or other metrics that you need as part of your constructor. Here, your controller class should look like this. (I've eliminated the duplicate AtomicLong, but you could add it back in as you showed if there's a specific reason you need it.)
#RestController
public class GreetingController {
private static final Logger LOG = LoggerFactory.getLogger(GreetingController.class);
private static final String template = "Hello, %s!";
private final Counter counter;
public GreetingController(MeterRegistry meterRegistry) {
counter = meterRegistry.counter("my.counter");
}
#RequestMapping("/greeting")
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
counter.increment();
long count = (long) counter.count();
return new Greeting(count, String.format(template, name));
}
}

AEM 6.3 - Creating Event handler using OSGi R6 annotations

I have created an Event handler by following https://github.com/nateyolles/aem-osgi-annotation-demo/blob/master/core/src/main/java/com/nateyolles/aem/osgiannotationdemo/core/listeners/SampleOsgiResourceListener.java and it works fine. However, I get the warning "The field SlingConstants.TOPIC_RESOURCE_ADDED is deprecated". I did some searching and found this thread :https://forums.adobe.com/thread/2325819
Here are the challenges that I am facing:
1) I want to create a separate configuration interface for my event handler. I tried this and it isn't working
package com.aem.sites.interfaces;
import org.apache.sling.api.SlingConstants;
import org.osgi.service.event.EventConstants;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
#ObjectClassDefinition(name = "Temperature Listener Configuration")
public #interface TemperatureListenerConfiguration {
#AttributeDefinition(
name = EventConstants.EVENT_FILTER,
description = "Configurable paths for temperature event listener",
type = AttributeType.STRING
)
String getPaths() default "/content/aemsite/en/jcr:content/root/responsivegrid/banner";
#AttributeDefinition(
name = EventConstants.EVENT_TOPIC,
description = "Event types",
type = AttributeType.STRING
)
String[] getEventTypes() default {SlingConstants.TOPIC_RESOURCE_ADDED,SlingConstants.TOPIC_RESOURCE_CHANGED, SlingConstants.TOPIC_RESOURCE_REMOVED};
}
package com.aem.sites.listeners;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.aem.sites.interfaces.TemperatureListenerConfiguration;
#Component(immediate=true,
service=EventHandler.class,
configurationPid = "com.aem.sites.listeners.EventHandler")
#Designate(ocd=TemperatureListenerConfiguration.class)
public class TemperaturePropertyListener implements EventHandler{
private final Logger logger = LoggerFactory.getLogger(getClass());
#Override
public void handleEvent(Event event) {
logger.info("*********************Event handler*****************************");
}
#Activate
#Modified
public void activate(TemperatureListenerConfiguration config) {
//config.getPaths();
logger.info("**************************TemperaturePropertyListener******************activate**********************");
}
}
I also want the solution for SlingConstants deprecated issue. Not sure if ResourceChangeListener is the answer to my problem and if yes then how everything is going to work together in the code.
Thanks in advance
===============================
Latest Code
package com.aem.sites.listeners;
import java.util.List;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.aem.sites.interfaces.TemperatureListenerConfiguration;
#Component(immediate=true,
service=ResourceChangeListener.class,
configurationPid = "com.aem.sites.listeners.TemperaturePropertyListener")
#Designate(ocd=TemperatureListenerConfiguration.class)
public class TemperaturePropertyListener implements ResourceChangeListener{
private final Logger logger = LoggerFactory.getLogger(getClass());
#Override
public void onChange(List<ResourceChange> changes) {
for (final ResourceChange change : changes) {
logger.info("**************************TemperaturePropertyListener******************change type**********************"+change.getType());
}
}
#Activate
#Modified
public void activate(TemperatureListenerConfiguration config) {
//config.getPaths();
logger.info("**************************TemperaturePropertyListener******************activate**********************");
}
}
The Interface
package com.aem.sites.interfaces;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
#ObjectClassDefinition(name = "Temperature Listener Configuration")
public #interface TemperatureListenerConfiguration {
#AttributeDefinition(
name = ResourceChangeListener.PATHS,
description = "Configurable paths for temperature event listener",
type = AttributeType.STRING
)
String[] getPaths() default {"/content/aemsite/en/jcr:content/root/responsivegrid/banner"};
#AttributeDefinition(
name = ResourceChangeListener.CHANGES,
description = "Event types",
type = AttributeType.STRING
)
String[] getEventTypes() default {"ADDED","REMOVED","CHANGED","PROVIDER_ADDED", "PROVIDER_REMOVED"};
}
Looking at the Javadoc for org.apache.sling.api.SlingConstants in sling 9 documentation here: http://sling.apache.org/apidocs/sling9/org/apache/sling/api/SlingConstants.html
it tells you specifically that TOPIC_RESOURCE_ADDED is deprecated:
Deprecated. Register a ResourceChangeListener instead
Read the documentation for ResourceChangeListener, additionally, you can take a look at a sample SCR service impl from ACS Samples:
It should not be hard to convert that to R6 declarative service.
Also, here are two examples from the sling project ResourceBackedPojoChangeMonitor and OsgiObservationBridge
Try to mimic those classes with the properties in the same class.

Minecraft Bukkit Events

I'm trying to get into bukkit programming for minecraft, but for some reason I'm stuck with events. Here's my code:
Main class file:
package com.plugin1;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginDescriptionFile;
//import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import net.md_5.bungee.api.ChatColor;
public class Plugin extends JavaPlugin {
public int songStage;
public static Plugin plugin;
public void OnEnable () {
PluginDescriptionFile pluginDesc = getDescription();
Logger logger = getLogger();
plugin = this;
registerEvents(this, new BlockBreak());
logger.info(pluginDesc.getName() + " is enabled! (V. " + pluginDesc.getVersion() + ")");
}
public void OnDisable () {
PluginDescriptionFile pluginDesc = getDescription();
Logger logger = Logger.getLogger("Plugin");
plugin = null;
logger.info(pluginDesc.getName() + " is disabled! (V. " + pluginDesc.getVersion() + ")");
}
public static void registerEvents(org.bukkit.plugin.Plugin plugin, Listener... listeners) {
for (Listener listener : listeners) {
Bukkit.getServer().getPluginManager().registerEvents(listener, plugin);
}
}
public static Plugin getPlugin() {
return plugin;
}
}
Event class file:
package com.plugin1;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
public class BlockBreak implements Listener {
#EventHandler(priority = EventPriority.HIGH)
public void OnBlockBreak (BlockBreakEvent e) {
Player p = e.getPlayer();
p.sendMessage("Block broken.");
}
}
Basically, this returns no errors. I've gone through console and there's nothing. When I break a block, literally nothing happens!
I've tried a few of things: I've gone through it, tried multiple video tutorials and tried a text tutorial on the minecraft forums but still nothing. I also contacted a server owner who codes bukkit plugins, but he couldn't fix this...
If there's anyone who can help me with this, PLEASE LET ME KNOW!!!!
Thanks in advance!
Here is a code example to start the server in a process:
package me.Nightfighter001.GlobalSystem.Listener;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import me.Nightfighter001.GlobalSystem.Main.main;
public class Join implements Listener {
public Join(main main) {
plugin = main;
plugin.getServer().getPluginManager().registerEvents(this, main);
}
#EventHandler
public void onPlayerJoin(PlayerJoinEvent ev) {
ev.setJoinMessage("");
}
main plugin = main.getPlugin();
}
I think you aren't registering the Listeners in the right way...
Try this code and tell me if it works... I'm really wanting to help you
First of all don't use "Plugin" as the name for your Main Class... Use "Main" instead.
Enable:
public class Main extends JavaPlugin {
public void onEnable() {
Bukkit.getPluginManger().registerEvents(new Join(this),this);
}
}
Listener:
public class Join implements Listener {
private Main plugin;
public Join(Main plugin) {
this.plugin = plugin;
}
#EventHandler
public void onPlayerJoin(PlayerJoinEvent ev) {
ev.setJoinMessage("Just another test");
}
}
Hope it works...
I've tested your code and it really doesn't work. I think your Eventregistration isn't working. For my plugins I use this in the mainClass:
package me.Nightfighter001.GlobalSystem.Main;
import org.bukkit.Bukkit;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import me.Nightfighter001.GlobalSystem.Listener.Join;
public class main extends JavaPlugin {
public static main getPlugin() {
return plugin;
}
private static main plugin;
#Override
public void onEnable() {
plugin = this;
new Join(this);
ConsoleCommandSender console = Bukkit.getConsoleSender();
console.sendMessage(new StringBuilder("\247c[\2476GlobalSystem\247c] \247bVersion \247c")
.append(getDescription().getVersion()).append(" \247bdes Plugins wurde aktiviert!").toString());
console.sendMessage(
"\247c[\2476GlobalSystem\247c] \247bDieses Plugin darf nur benutzt werden, wenn der Entwickler \247cNightfighter001 \247bes erlaubt!");
return;
}
#Override
public void onDisable() {
ConsoleCommandSender console = Bukkit.getConsoleSender();
console.sendMessage(new StringBuilder("\247c[\2476GlobalSystem\247c] \247bVersion \2474")
.append(getDescription().getVersion()).append(" \247bdes Plugins wurde deaktiviert!").toString());
}
}
And in the EventClass:
package me.Nightfighter001.GlobalSystem.Listener;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import me.Nightfighter001.GlobalSystem.Main.main;
public class Join implements Listener {
public Join(main main) {
plugin = main;
plugin.getServer().getPluginManager().registerEvents(this, main);
}
#EventHandler
public void onPlayerJoin(PlayerJoinEvent ev) {
ev.setJoinMessage("");
}
main plugin = main.getPlugin();
}
As you can see in my example I use the PlayerJoinEvent, but it also works with the BlockBreakEvent. I hope this helps :) And sorry for my bad English ;D
Your code will work if you don't capitalize the names of the onEnable (and onDisable) methods. onEnable and OnEnable are two different methods since java is case sensitive, and since you're trying to override specific methods in the JavaPlugin super class, you'll need to spell them the exact same way.
Common convention is, as far as I know, that you start your methods with lowercase letters anyway though. The #Override annotation is very useful in catching these kinds of bugs, because it lets the compiler know that you mean to override an existing method, and if that method doesn't exist (for example if you misspelled the name or added different parameters), it will alert you (it also lets anyone reading the code immediately know you're overriding an existing method or implementing an interface).

Categories