JavaFX Why AnimationTimer has not getStatus() or similar method? - javafx

It seems pretty strange that AnimationTimer has not a method to know if it is running or not.... And i am facing this problem, cause sometimes it is starting and sometimes not.
A solution is creating a volatile variable inside the handle() method and every time it is running inside the handle to make it true and every time it enters stop()) method to make it false.So i have to #Override both methods.
The Question:
Why the AnimationTimer has not a method to determine if it is running?
Is it a bad design it is missing for some reason?
Relative questions:
Is AnimationTimer running in its own thread?
How can I know if an AnimationTimer is running?

It is indeed very strange that this method is missing but with the exception of you and me nobody seems to care. I have reported this issue
more than 4 years ago and nothing has happened since then although the fix seems to be trivial.
JDK-8092345

From now it has the method isRunning() until bro's from Oracle add it🐠.
By looking here although it is not present in Java 9 http://download.java.net/java/jdk9/jfxdocs/javafx/animation/AnimationTimer.html.
AnimationTimer code:
/*
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.sun.javafx.tk.Toolkit;
import com.sun.scenario.animation.AbstractMasterTimer;
import com.sun.scenario.animation.shared.TimerReceiver;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* The class {#code AnimationTimer} allows to create a timer, that is called in
* each frame while it is active.
*
* An extending class has to override the method {#link #handle(long)} which
* will be called in every frame.
*
* The methods {#link AnimationTimer#start()} and {#link #stop()} allow to start
* and stop the timer.
*
*
* #since JavaFX 2.0
*/
public abstract class AnimationTimer {
private class AnimationTimerReceiver implements TimerReceiver {
#Override public void handle(final long now) {
if (accessCtrlCtx == null) {
throw new IllegalStateException("Error: AccessControlContext not captured");
}
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
AnimationTimer.this.handle(now);
return null;
}, accessCtrlCtx);
}
}
private final AbstractMasterTimer timer;
private final AnimationTimerReceiver timerReceiver = new AnimationTimerReceiver();
private boolean active;
// Access control context, captured in start()
private AccessControlContext accessCtrlCtx = null;
/**
* Creates a new timer.
*/
public AnimationTimer() {
timer = Toolkit.getToolkit().getMasterTimer();
}
// For testing only
AnimationTimer(AbstractMasterTimer timer) {
this.timer = timer;
}
/**
* This method needs to be overridden by extending classes. It is going to
* be called in every frame while the {#code AnimationTimer} is active.
*
* #param now
* The timestamp of the current frame given in nanoseconds. This
* value will be the same for all {#code AnimationTimers} called
* during one frame.
*/
public abstract void handle(long now);
/**
* Starts the {#code AnimationTimers}. Once it is started, the
* {#link #handle(long)} method of this {#code AnimationTimers} will be
* called in every frame.
*
* The {#code AnimationTimers} can be stopped by calling {#link #stop()}.
*/
public void start() {
if (!active) {
// Capture the Access Control Context to be used during the animation pulse
accessCtrlCtx = AccessController.getContext();
timer.addAnimationTimer(timerReceiver);
active = true;
}
}
/**
* Stops the {#code AnimationTimers}. It can be activated again by calling
* {#link #start()}.
*/
public void stop() {
if (active) {
timer.removeAnimationTimer(timerReceiver);
active = false;
}
}
/**Determines if the AnimationTimer is Running
* #return True if it is running
*/
public boolean isRunning() {
return active;
}
}

Related

Can a DTO reference VO of the domain model?

Question
Can a data transfer object (DTO) reference a value object (VO) of the domain model?
Context
In my domain, I've an importer which import aggregates from a collection. The collection is made of DTO build by a collector on which the importer rely. Since both the importer and collector are services (interfaces) of my domain, can the DTO reference domain value objects, or should I stick with primitives and turn them into value objects only when processing the collection (build of aggregates)?
Collector implementation where DTO made of value objects from the domain model are built
<?php
/**
* i-MSCP Patcher plugin
*
* #author Laurent Declercq <l.declercq#nuxwin.com>
* #copyright (C) 2019 Laurent Declercq <l.declercq#nuxwin.com>
* #license i-MSCP License <https://www.i-mscp.net/license-agreement.html>
*/
/**
* #noinspection
* PhpUnhandledExceptionInspection
* PhpDocMissingThrowsInspection
*/
declare(strict_types=1);
namespace iMSCP\Plugin\Patcher\Infrastructure\Domain\Service\Component\Importer;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentBuild;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentName;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentVersion;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\ComponentCollector;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\DTO\ComponentDTO;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\DTO\ComponentDTOCollection;
use iMSCP_Config_Handler_File as MergedConfig;
use iMSCP_Plugin_Manager as PluginManager;
use RuntimeException;
use Throwable;
/**
* Class DefaultComponentCollector
* #package iMSCP\Plugin\Patcher\Infrastructure\Domain\Service\Component\Importer
*/
class DefaultComponentCollector implements ComponentCollector
{
/**
* #var MergedConfig
*/
private $mergedConfig;
/**
* #var PluginManager
*/
private $pluginManager;
/**
* DefaultComponentCollector constructor.
*
* #param MergedConfig $mergedConfig
* #param PluginManager $pluginManager
*/
public function __construct(
MergedConfig $mergedConfig, PluginManager $pluginManager
)
{
$this->mergedConfig = $mergedConfig;
$this->pluginManager = $pluginManager;
}
/**
* #inheritDoc
*/
public function collect(ComponentDTOCollection $collection): void
{
try {
// Core
$collection->add(new ComponentDTO(
ComponentName::fromString('core'),
ComponentVersion::fromString($this->mergedConfig['Version']),
ComponentBuild::fromString($this->mergedConfig['Build'])
));
// Plugins
$this->collectComponentsFromCorePluginManager($collection);
} catch (Throwable $e) {
throw new RuntimeException(sprintf(
"Couldn't collect list of components: %s", $e->getMessage()
), $e->getCode(), $e);
}
}
/**
* Collects components from the i-MSCP core plugin manager.
*
* #param ComponentDTOCollection $collection
* #return void
*/
private function collectComponentsFromCorePluginManager(
ComponentDTOCollection $collection
): void
{
$pluginList = $this->pluginManager->pluginGetList('all', false);
foreach ($pluginList as $pluginName) {
$pluginInfo = $this->pluginManager
->pluginGetInfo($pluginName)
->toArray();
$componentDTO = new ComponentDTO(
ComponentName::fromString($pluginInfo['name']),
ComponentVersion::fromString($pluginInfo['version']),
ComponentBuild::fromString((string)$pluginInfo['build'])
);
$collection->add($componentDTO);
}
}
}
Can a data transfer object (DTO) reference a value object (VO) of the domain model?
Yes, but you want to be very careful about doing that.
A data transfer object is, at its core, a message. For a message to serve its purpose, both the sender and the receiver must have compatible understandings of its semantics. Making an incompatible change to the DTO schema requires corresponding changes to the receiver.
A value object, in the domain model, is not a message. It is structured information, purely an implementation detail of the current model. If we want to deploy a new version of our model, which uses a completely different arrangement of values, or their underlying data structures, then we can.
So having a DTO (which is supposed to be stable) depend on a value object (which does not promise to be stable) is creating an opportunity for problems down the road.
In cases where your vocabulary of values is stable, then the risks are lower.

Inject service based on dynamic value in Symfony

I have 2 services, BlueWorkerService and YellowWorkerService, both implementing the same interface, WorkerServiceInterface. Each of these services use the same entities but with different required logic.
I need to inject one of, but not both, of these classes and use them in ProcessorService so that the interface methods are called using on correct Worker. Which worker service to use is dependent on which Worker is currently being processed. I'll break it down:
Class WorkerProcessor {
private $workerService;
public function __construct(WorkerServiceInterface $workerServiceInterface)
{
$this->workerService = $workerServiceInterface;
}
public function getMixedColourWithRed() {
return $this->workerService->mixWithRed();
}
}
The worker service that is being used would be based on whether the worker being processed has the colour property of Blue or Yellow.
I know I can probably use a Factory to achieve this as described here but my problem is how to tell the factory which Worker colour I am processing?
Running on Symfony 3.4
If you need more info, just ask and I will update the question.
NOTE: I'm using Symfony 4.3.1. I'll post it like that, then I'll help you to move all code from this architecture to Symfony 3.4.
I'm using a similar concept to load different classes in my project. Let me explain first, then I'll add code under this text.
Firstly, I'm loading a custom compiler pass under src/Kernel.php (your file is app/AppKernel.php):
/**
* {#inheritDoc}
*/
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new BannerManagerPass());
}
BannerManagerPass its created under src/DependencyInjection/Compiler (in your case should be src/BUNDLE/DependencyInjection/Compiler`).
class BannerManagerPass implements CompilerPassInterface
{
/**
* {#inheritDoc}
*/
public function process(ContainerBuilder $container)
{
if (!$container->has(BannerManager::class)) {
return;
}
$definition = $container->findDefinition(BannerManager::class);
$taggedServices = $container->findTaggedServiceIds('banner.process_banners');
foreach (array_keys($taggedServices) as $id) {
$definition->addMethodCall('addBannerType', [new Reference($id)]);
}
}
}
As you see, this class should implement CompilerPassInterface. You can observe that I'm looking for specific services tagged as banner.process_banners. I'll show how I tagged services a little bit later. Then, I'm calling addBannerType method from BannerManager.
App\Service\BannerManager.php: (in your case src/BUNDLE/Service/BannerManager.php)
class BannerManager
{
/**
* #var array
*/
private $bannerTypes = [];
/**
* #param BannerInterface $banner
*/
public function addBannerType(BannerInterface $banner)
{
$this->bannerTypes[$banner->getType()] = $banner;
}
/**
* #param string $type
*
* #return BannerInterface|null
*/
public function getBannerType(string $type)
{
if (!array_key_exists($type, $this->bannerTypes)) {
return null;
}
return $this->bannerTypes[$type];
}
/**
* Process request and return banner.
*
* #param string $type
* #param Server $server
* #param Request $request
*
* #return Response
*/
public function process(string $type, Server $server, Request $request)
{
return $this->getBannerType($type)->process($request, $server);
}
}
This class has a custom method (created by me) called process(). You can name it whatever you want it, but I think that's pretty verbose. All parameters are sent by me, so don't mind. You can send whatever you want.
Now we have our Manager and compiler pass is set. It's time to set our banner types (based on my example) and tag them!
My banner types are under src/Service/Banner/Types (in your case should be src/BUNDLE/Service/WhateverYouWant/Type. This does not matter! You can change it later from services.yaml).
These types are implementing my BannerInterface. It does not matter the code under the class in this instance. One more thing that I should warn you! You should see that under BannerManager, inside the addBannerType() I'm calling $banner->getType(). This is one method inherited from BannerInterface in my case and it has a unique string (in my example I have three banner types: small, normal, large). This method can have any name, but don't forget to update it as well in your manager.
We are almost ready! We should tag them, then we are ready to try them!
Go to your services.yaml and add these lines:
App\Service\Banner\Types\:
resource: '../src/Service/Banner/Types/'
tags: [banner.process_banners]
Please see the tag!
Whatever I want to show a custom banner, I'm using a simple URL with $_GET where I keep my banner type, then I load it like this:
public function view(?Server $server, Request $request, BannerManager $bannerManager)
{
...
return $bannerManager->getBannerType($request->query->get('slug'))->process($request, $server);
}

inconsistent mapping in symfony

I have two entities, User and Notification. In each notification, there is a sender and receiver that are both User entities. But doctrine doesn't like it. The schema validation says:
The mappings ACME\CoreBundle\Entity\Notifications#sender and ACME\CoreBundle\Entity\User#notifications are inconsistent with each other.
Here are the mappings for both entities:
/**
* Notifications
*
* #ORM\Table(name="notifications")
*
*/
class Notifications
{
/**
* #ORM\ManyToOne(targetEntity="WD\UserBundle\Entity\User", inversedBy="notifications")
*/
protected $sender;
/**
* #ORM\ManyToOne(targetEntity="WD\UserBundle\Entity\User", inversedBy="notifications")
*/
protected $receiver;
}
And the User one:
/**
* User
*
* #ORM\Table(name="My_user")
*
*/
class User extends BaseUser
{
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="WD\CoreBundle\Entity\Notifications", mappedBy="receiver")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $notifications;
}
For readability reasons, I did not put the whole entities code, but I believe these should be enough info.
I believe the error comes from the fact I cannot put two 'mappedBy" values in User entity, but I'm not sure. And if it is, then I have no idea how to fix this.
I've found kinda similar cases on this website, but none that was exactly like mine (or I haven't found them).
Any idea how I could fix this?
I think the issue might be that you're having two properties (sender, receiver) and using the same column to map them. If you need to distinguish between sent and received, you'll need to have sender and receiver properties on Notification and then in your user have sentNotifications and receivedNotifications. You can combine them in an un-mapped method in your User if you do need to get everything together in one call such as:
/**
* #var Notification[]|ArrayCollection
*/
public function getAllNotifications()
{
return new ArrayCollection(
array_merge(
$this->sentNotifications->toArray(),
$this->receivedNotifications->toArray()
)
);
}

Symfony - SeoBundle built EMPTY sitemap

I installed SeoBundle and configured the bundle to build a sitemap (docs).
AppKernel.php:
new Sonata\SeoBundle\SonataSeoBundle(),
new Symfony\Cmf\Bundle\CoreBundle\CmfCoreBundle(),
new Symfony\Cmf\Bundle\SeoBundle\CmfSeoBundle(),
Full bundle configurations (config.yml):
sonata_seo:
page:
title: Erasmus internship – Training Experience
metas:
name:
keywords: Erasmus Internships, Internship in Europe, International Internships, Erasmus+, Erasmus Entrepreneur, Student Internships, Internships Abroad, Student Placements
description: Find Internships with Training Experience: Students can find internships & employment opportunities in Europe’s platform for internships. Search paid internships and placements abroad.
viewport: width=device-width, initial-scale=1
format-detection: telephone=no
robots: index, follow
property:
'og:site_name': Training Experience
'og:title': Erasmus internship – Training Experience
'og:description': Find Internships with Training Experience: Students can find internships & employment opportunities in Europe’s platform for internships. Search paid internships and placements abroad."
'og:url': https://www.trainingexperience.org
'og:image': https://www.trainingexperience.org/bundles/index/images/tx-orange.png
http-equiv:
'Content-Type': text/html; charset=utf-8
head:
'xmlns': http://www.w3.org/1999/xhtml
'xmlns:og': http://opengraphprotocol.org/schema/
cmf_seo:
title: seo.title
description: seo.description
sitemap:
enabled: true
content_listener:
enabled: false
Added routes to routing.yml:
sitemaps:
prefix: /sitemaps
resource: "#CmfSeoBundle/Resources/config/routing/sitemap.xml"
Now when I access /sitemaps/sitemap.xml it is opened, but no urls are listed:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"></urlset>
What could I be missing?
Important for the items on sitemat is, that they got a matching (allowed, and sitemap name) as a content. Mostly the content isn't loaded. To do so your Content have to implement \Symfony\Cmf\Bundle\SeoBundle\SitemapAwareInterface, which forces you to implement and fill a flag. You can find an example in the tests: SitemapAwareContent:
<?php
/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2017 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Cmf\Bundle\SeoBundle\Tests\Resources\Document;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCRODM;
use Symfony\Cmf\Bundle\CoreBundle\Translatable\TranslatableInterface;
use Symfony\Cmf\Bundle\SeoBundle\SitemapAwareInterface;
use Symfony\Cmf\Component\Routing\RouteReferrersReadInterface;
use Symfony\Component\Routing\Route;
/**
* #PHPCRODM\Document(referenceable=true, translator="attribute")
*
* #author Maximilian Berghoff <Maximilian.Berghoff#gmx.de>
*/
class SitemapAwareContent extends ContentBase implements RouteReferrersReadInterface, TranslatableInterface, SitemapAwareInterface
{
/**
* #var string
*
* #PHPCRODM\Locale
*/
protected $locale;
/**
* #var ArrayCollection|Route[]
*
* #PHPCRODM\Referrers(
* referringDocument="Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\Route",
* referencedBy="content"
* )
*/
protected $routes;
/**
* #var bool
*
* #PHPCRODM\Field(type="boolean",property="visible_for_sitemap")
*/
private $isVisibleForSitemap;
/**
* #var string
*
* #PHPCRODM\Field(type="string",translated=true)
*/
protected $title;
public function __construct()
{
$this->routes = new ArrayCollection();
}
/**
* #param string $sitemap
*
* #return bool
*/
public function isVisibleInSitemap($sitemap)
{
return $this->isVisibleForSitemap;
}
/**
* #param bool $isVisibleForSitemap
*
* #return SitemapAwareContent
*/
public function setIsVisibleForSitemap($isVisibleForSitemap)
{
$this->isVisibleForSitemap = $isVisibleForSitemap;
return $this;
}
/**
* Add a route to the collection.
*
* #param Route $route
*/
public function addRoute($route)
{
$this->routes->add($route);
}
/**
* Remove a route from the collection.
*
* #param Route $route
*/
public function removeRoute($route)
{
$this->routes->removeElement($route);
}
/**
* Get the routes that point to this content.
*
* #return Route[] Route instances that point to this content
*/
public function getRoutes()
{
return $this->routes;
}
/**
* #return string|bool the locale of this model or false if
* translations are disabled in this project
*/
public function getLocale()
{
return $this->locale;
}
/**
* #param string|bool $locale the local for this model, or false if
* translations are disabled in this project
*/
public function setLocale($locale)
{
$this->locale = $locale;
}
}
you will also see that implementing the interface isn't the only task, you have to set the doctrine mapping also. Doing so, the default loader will fetch you documents and see them (they are visible now).
But you can implement your own loader, voter (another decission item to select) and guesser (to fill in extra data) on your own. So you can decide which content is visible on which (you can have several) sitemap.
The documentation currently shows the process for the loaders, voter and guessers only, so we should insert some hints for the default visibility flag and the default usage at all. So i created an issue. It would be nice to get some feedback there, too.

How can I issue one Insert statement for multiple rows in Propel

is there a way to issue one INSERT statement instead of calling save() method on each object? Can I call save() on PropelObjectCollection?
You can call save on a PropelObjectCollection from the class itself but it will issue multiple insert statements to do the work.
There is not much of a performance gain from issuing one INSERT rather than multiple if they are all wrapped in a transaction which Propel does by default. Also given the way Propel recurses to save related objects I suspect trying to do this would add a lot of complexity.
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* #license MIT License
*/
/**
* Class for iterating over a list of Propel objects
*
* #author Francois Zaninotto
* #package propel.runtime.collection
*/
class PropelObjectCollection extends PropelCollection
{
/**
* Save all the elements in the collection
*
* #param PropelPDO $con
*
* #throws PropelException
*/
public function save($con = null)
{
if (!method_exists($this->getModel(), 'save')) {
throw new PropelException('Cannot save objects on a read-only model');
}
if (null === $con) {
$con = $this->getConnection(Propel::CONNECTION_WRITE);
}
$con->beginTransaction();
try {
/** #var $element BaseObject */
foreach ($this as $element) {
$element->save($con);
}
$con->commit();
} catch (PropelException $e) {
$con->rollback();
throw $e;
}
}
It is enough to put all of your save() calls in one transaction. In my code I had to insert 270 records in MySQL database.
Results without transactions:
real 0m15.127s
user 0m0.300s
sys 0m0.056s
Results with transactions:
real 0m0.687s
user 0m0.244s
sys 0m0.036s
There is a huge difference.

Resources