Cron jobs with Bolt - cron

Just a quick question on task scheduling and extending with Bolt CM.
Documentation: https://docs.bolt.cm/v20/tasks
When adding task scheduling to an extension, does the listener have to be specified outside of the class?
use Bolt\CronEvents;
$this->app['dispatcher']->addListener(CronEvents::CRON_INTERVAL, array($this, 'myJobCallbackMethod'));
class MyExtension extends \Bolt\BaseExtension {
// ...
Or does it need to be declared in the initialize function?
use Bolt\CronEvents;
class MyExtension extends \Bolt\BaseExtension {
public function initialize() {
$this->app['dispatcher']->addListener(CronEvents::CRON_INTERVAL, array($this, 'myJobCallbackMethod'));
}
// ...
I assume it's the latter because $this outside of the class would be outside of the object context. The documentation makes it look as if it directly follows, so thought I'd double check.

You are correct, the $this->app['dispatcher']->addListener() call does need to be in a class context.
Oversimplification in the docs there.

I got it in initialize function and it works fine
public function initialize()
{
$this->app['dispatcher']->addListener(CronEvents::CRON_DAILY, array($this, 'run'));
}
public function run(){
// code to run
}

Related

Is it possible to use the Slugger interface other than in a constructor?

I'm looking to use the sluggerInterface in a class. But I want to keep:
public function __construct()
{
}
So I want to use sluggerInterface in my class without adding any argument in my constructor. (this is in order to automatically create 1 slug when creating an object).
So I want a code different from this one:
use Symfony\Component\String\Slugger\SluggerInterface;
class MyService
{
private $slugger;
public function __construct(SluggerInterface $slugger)
{
$this->slugger = $slugger;
}
public function someMethod()
{
$slug = $this->slugger->slug('...');
}
}
Thank you !
You do not want to use autowiring in your constructor ?
You could just create a new slugger, for example with Symfony\Component\String\Slugger\AsciiSlugger;
$slugger = new AsciiSlugger();
$slugger->slug('Please slug this.')->toString();
Or you could also use autowiring with another method using #required annotation (or attribute #[Required] for PHP 8+)
private $slugger;
#[Required]
public function setSlugger(SluggerInterface $slugger): void
{
$this->slugger= $slugger;
}
this is in order to automatically create 1 slug when creating an object
You may also want to look into event listener, using doctrine event prePersist to slug your entity when persisted could be another idea.
Finally, gedmo doctrine-extensions sluggable may interest you as well.

How can I run code in JUnit before Spring starts?

How can I run code in my #RunWith(SpringRunner.class) #SpringBootTest(classes = {...}) JUnit test before Spring starts?
This question has been asked several times (e.g. 1, 2) but was always "solved" by some configuration recommendation or other, never with a universal answer. Kindly don't question what I am about to do in that code but simply suggest a clean way to do it.
Tried so far and failed:
Extend SpringJUnit4ClassRunner to get a class whose constructor can run custom code before initializing Spring. Failed because super(testClass) must be called first thing and already does a whole lot of things that get in the way.
Extend Runner to get a class that delegates to SpringRunner instead of inheriting it. This class could run custom code in its constructor before actually instantiating the SpringRunner. However, this setup fails with obscure error messages like java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig. "Obscure" because my test has no web config and thus shouldn't meddle with sessions and cookies.
Adding an ApplicationContextInitializer that is triggered before Spring loads its context. These things are easy to add to the actual #SpringApplication, but hard to add in Junit. They are also quite late in the process, and a lot of Spring has already started.
One way to do it is to leave out SpringRunner and use the equivalent combination of SpringClassRule and SpringMethodRule instead. Then you can wrap the SpringClassRule and do your stuff before it kicks in:
public class SomeSpringTest {
#ClassRule
public static final TestRule TestRule = new TestRule() {
private final SpringClassRule springClassRule =
new SpringClassRule();
#Override
public Statement apply(Statement statement, Description description) {
System.out.println("Before everything Spring does");
return springClassRule.apply(statement, description);
}
};
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
#Test
public void test() {
// ...
}
}
(Tested with 5.1.4.RELEASE Spring verison)
I don't think you can get more "before" than that. As for other options you could also check out #BootstrapWith and #TestExecutionListeners annotations.
Complementing jannis' comment on the question, the option to create an alternative JUnit runner and let it delegate to the SpringRunner does work:
public class AlternativeSpringRunner extends Runner {
private SpringRunner springRunner;
public AlternativeSpringRunner(Class testClass) {
doSomethingBeforeSpringStarts();
springRunner = new SpringRunner(testClass);
}
private doSomethingBeforeSpringStarts() {
// whatever
}
public Description getDescription() {
return springRunner.getDescription();
}
public void run(RunNotifier notifier) {
springRunner.run(notifier);
}
}
Being based on spring-test 4.3.9.RELEASE, I had to override spring-core and spring-tx, plus javax.servlet's servlet-api with higher versions to make this work.

ActiveWeb: mocking injected service

When mocking a service injected into a controller, a service method should return a mocked object, something like that:
public class EmptyInterventionServiceMock implements InterventionService {
#Override
public Intervention findByInvoiceNumber(String invoiceNumber, String language) {
return mockedIntervention(invoiceNumber, language);
}
protected Intervention mockedIntervention(String invoiceNumber, String language) {
return mock(Intervention.class);
}
}
Is it possible to mock some values to be return by the above mocked object (Intervention) to test fi they should be present in the generated JSON template ?
For example, depending on if Intervention has spare parts, services, states (all of them are just collections of other objects), etc. If so, JSON should contain the corresponding keys: services: [{....}], states: [{}], etc.
It would be nice to get the mocked object in the test and stub its return values. The only way I see to achieve that for the moment is to create a separate Mock service class and inject it in a test class as follows:
public class InterventionsControllerSpec extends ControllerSpec {
#Before
public void before() {
Injector injector = injector().bind(InterventionService.class).to(BaseInterventionServiceMock.class).create();
}
Where BaseInterventionServiceMock just extends EmptyInterventionServiceMock and stubs some methods return values by overriding its mockedIntervention method:
public class BaseInterventionServiceMock extends EmptyInterventionServiceMock {
#Override
protected Intervention mockedIntervention(String invoiceNumber, String language) {
Intervention intervention = mock(Intervention.class);
when(intervention.getString("ITV_DOCUMENT_NUMBER")).thenReturn("123");
when(intervention.getString("ITV_INVOICE")).thenReturn(invoiceNumber);
...
etc.
As it is far from ideal, I wonder if there is a DRYer way to do that ?
Thank you.
You are not missing anything. Your assumptions are correct. Creating a mock subclass of a service is how we do the testing. If you want a more elegant way, you can submit a proposal for consideration: https://github.com/javalite/activeweb/issues for consideration.

Calling Method of class within it

// What is the technical reason behind this scenarios..?
You're trying to use a statement other than a declaration directly inside the class - rather than within a method. When did you expect the method to get called?
Basically all you can have directly within a type is a bunch of declarations - methods, variables, constructors, events, nested types etc. Method calls (or any other statements) which aren't part of a declaration have to be written within methods, constructors etc.
Method call statement can not be part of a class declaration, but only within Function members declarations scope, such as Methods, Properties, Constructors etc.
For example:
public class ExampleClass
{
private void SayHelloWorld()
{
Console.Writeline("Hello World!");
}
public void CallSayHelloWorldMethod()
{
this.SayHelloWorld();
}
}
At the above example you can see that I call the SayHelloWorld method within the CallSayHelloWorldMethod metod.
Update:
The closest thing I can think of in your case is to use the class's constructor where your method call will be executed as soon as you'll instantiate your class:
public class ExampleClass
{
//The class constructor
public ExampleClass()
{
this.SayHelloWorld();
}
private void SayHelloWorld()
{
Console.Writeline("Hello World!");
}
}
And when you instantiating it, it will be immediately called:
//Your method call will be executed here
ExampleClass exampleClass = new ExampleClass();
You have a few problems... This won't even compile as you are trying to call the method obj.m1() in the class definition.
A obj = new A();
obj.m1(); // Why this code wont work??? --> This must be inside a method
When you create an instance of a class it will create a new member variable called obj which is an instance of A --> A obj = newA() above;
You will now be able to call obj's methods as in your second example.
Also, in order to get this to compile you will need to fix the m2 method:
public void m2() { //--> should have a curly brace
obj.m1(); // But This will work.
}

ViewHelper newable/injectable dilemma

I'm trying to design an application following Misko Heverys insights. It's an interesting experiment and a challenge. Currently I'm struggling with my ViewHelper implementation.
The ViewHelper decouples the model from the view. In my implementation it wraps the model and provides the API for the view to use. I'm using PHP, but I hope the implementation is readable for everyone:
class PostViewHelper {
private $postModel;
public function __construct(PostModel $postModel) {
$this->postModel = $postModel;
}
public function title() {
return $this->postModel->getTitle();
}
}
In my template (view) file this could be called like this:
<h1><?php echo $this->post->title(); ?></h1>
So far so good. The problem I have is when I want to attach a filter to the ViewHelpers. I want to have plugins that filter the output of the title() call. The method would become like this:
public function title() {
return $this->filter($this->postModel->getTitle());
}
I need to get observers in there, or an EventHandler, or whatever service (in what I see as a newable, so it needs to be passed in through the stack). How can I do this following the principles of Misko Hevery? I know how I can do this without it. I'm interested in how for I can take it and currently I don't see a solution. ViewHelper could be an injectable too, but then getting the model in there is the problem.
I didn't find the blog post you referenced very interesting or insightful.
What you are describing seems more like a Decorator than anything to do with dependency injection. Dependency injection is how you construct your object graphs, not their state once constructed.
That said, I'd suggest taking your Decorator pattern and running with it.
interface PostInterface
{
public function title();
}
class PostModel implements PostInterface
{
public function title()
{
return $this->title;
}
}
class PostViewHelper implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->post->title();
}
}
class PostFilter implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->filter($this->post->title());
}
protected function filter($str)
{
return "FILTERED:$str";
}
}
You'd simply use whatever DI framework you have to build this object graph like so:
$post = new PostFilter(new PostViewHelper($model)));
I often use this approach when building complex nested objects.
One problem you might run into is defining "too many" functions in your PostInterface. It can be a pain to have to implement these in every decorator class. I take advantage of the PHP magic functions to get around this.
interface PostInterface
{
/**
* Minimal interface. This is the accessor
* for the unique ID of this Post.
*/
public function getId();
}
class SomeDecoratedPost implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->_post = $post;
}
public function getId()
{
return $this->_post->getId();
}
/**
* The following magic functions proxy all
* calls back to the decorated Post
*/
public function __call($name, $arguments)
{
return call_user_func_array(array($this->_post, $name), $arguments);
}
public function __get($name)
{
return $this->_post->get($name);
}
public function __set($name, $value)
{
$this->_post->__set($name, $value);
}
public function __isset($name)
{
return $this->_post->__isset($name);
}
public function __unset($name)
{
$this->_post->__unset($name);
}
}
With this type of decorator in use, I can selectively override whatever method I need to provide the decorated functionality. Anything I don't override is passed back to the underlying object. Multiple decorations can occur all while maintaining the interface of the underlying object.

Resources