I have a datatransformer in symfony 2:
namespace Techforge\ApartmentBundle\Form\DataTransformer;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Common\Persistence\ObjectManager;
class SearchboxToCityTransformer implements DataTransformerInterface {
public function reverseTransform($string)
{
//...
if(!$city)
throw new TransformationFailedException(sprintf('City not found.'));
}
//...
I can't figure out how to catch this exception in my controller.
I thought it was going to be thrown upon a form bind:
$form->bindRequest($request);
But that doesn't appear to be the case (I tested this out, and also tested out other parts in my controller).
Also, I'm pretty sure that I triggered the exception because the field didn't appear in the parameter bag (nothing was returned from the reverseTrasnform() function.)
Anyone has any ideas?
The short answer is: you don't.
Take a look at Symfony\Component\Form\Form::bind()
try {
// Normalize data to unified representation
$normData = $this->clientToNorm($clientData);
$synchronized = true;
} catch (TransformationFailedException $e) {
}
So TransformationFailedException are silently ignored. The behaviors is a bit puzzling but more than likely you are trying to do validation inside of a transformer which is not what transformers were intended for.
Move the error checking code code to a validator and things should fall into place.
TransformationFailedExceptions will result in an invalid field in the form. If you want the exception to bubble up higher, throw a different exception.
Related
I would like to use the PUT method for creating resources. They are identified by an UUID, and since it is possible to create UUIDs on the client side, I would like to enable the following behaviour:
on PUT /api/myresource/4dc6efae-1edd-4f46-b2fe-f00c968fd881 if this resource exists, update it
on PUT /api/myresource/4dc6efae-1edd-4f46-b2fe-f00c968fd881 if this resource does not exist, create it
It's possible to achieve this by implementing an ItemDataProviderInterface / RestrictedDataProviderInterface.
However, my resource is actually a subresource, so let's say I want to create a new Book which references an existing Author.
My constructor looks like this:
/**
* Book constructor
*/
public function __construct(Author $author, string $uuid) {
$this->author = $author;
$this->id = $uuid;
}
But I don't know how to access the Author entity (provided in the request body) from my BookItemProvider.
Any ideas?
In API Platform many things that should occur on item creation is based on the kind of request it is. It would be complicated to change.
Here are 2 possibilities to make what you want.
First, you may consider to do a custom route and use your own logic. If you do it you will probably be happy to know that using the option _api_resource_class on your custom route will enable some listeners of APIPlaform and avoid you some work.
The second solution, if you need global behavior for example, is to override API Platform. Your main problem for this is the ReadListener of ApiPlatform that will throw an exception if it can't found your resource. This code may not work but here is the idea of how to override this behavior:
class CustomReadListener
{
private $decoratedListener;
public function __construct($decoratedListener)
{
$this->decoratedListener = $decoratedListener;
}
public function onKernelRequest(GetResponseEvent $event)
{
try {
$this->decoratedListener->onKernelRequest($event);
} catch (NotFoundHttpException $e) {
// Don't forget to throw the exception if the http method isn't PUT
// else you're gonna break the 404 errors
$request = $event->getRequest();
if (Request::METHOD_PUT !== $request->getMethod()) {
throw $e;
}
// 2 solutions here:
// 1st is doing nothing except add the id inside request data
// so the deserializer listener will be able to build your object
// 2nd is to build the object, here is a possible implementation
// The resource class is stored in this property
$resourceClass = $request->attributes->get('_api_resource_class');
// You may want to use a factory? Do your magic.
$request->attributes->set('data', new $resourceClass());
}
}
}
And you need to specify a configuration to declare your class as service decorator:
services:
CustomReadListener:
decorate: api_platform.listener.request.read
arguments:
- "#CustomReadListener.inner"
Hope it helps. :)
More information:
Information about event dispatcher and kernel events: http://symfony.com/doc/current/components/event_dispatcher.html
ApiPlatform custom operation: https://api-platform.com/docs/core/operations#creating-custom-operations-and-controllers
Symfony service decoration: https://symfony.com/doc/current/service_container/service_decoration.html
I want some kind of mechanism to have more information about a caught exception. (Specifically exceptions I throw myself to abort transactions) I've looked around and pretty much the only thing I could find was "Use the info log". This to me does not seem like a good idea. For one it is cumbersome to access and find the last message. And it is limited in size so at some point the new messages won't even show up.
So my idea is the following: Create a class NuException and pass an instance of that through all methods store an instance in the class where the work methods are located. When I need to throw an exception I call a method on it similar to Global::error() but this one takes an identifier and a message.
Once I reach my catch block I can access those from my object the class that contains the work methods similarly to how CLRExceptions work.
class NuException
{
"public" str identifier;
"public" str message;
public Exception error(str _id, str _msg)
{
//set fields
return Exception::Error;
}
}
class Worker
{
"public" NuException exception;
void foo()
{
throw this.exception.error("Foo", "Record Foo already exists");
}
void bar()
{
this.foo();
}
}
void Job()
{
Worker w = new Worker();
try
{
w.bar(ex);
}
catch (Exception::Error)
{
info(w.exception().message());
}
}
It works but isn't there a better way? Surely someone must have come up with a solution to work around this shortcoming in AX?
Short answer: yes.
While your "brilliant" scheme "works", it gets boring pretty fast, as you now must transport your NuException object deep down 20 level from the listener (job) to the thrower (foo). Your bar method and other middle men has no interest or knowledge about your exception scheme but must pass it on anyway.
This is no longer the case after the update.
There are several ways to go.
Use an observer pattern like the Event broker or in AX 2012 and newer use delegates.
Stick to the infolog system and you use an InfoAction class to peggy bag your information to be used later. It can be used to display a stack trace or other interesting information.
Use a dedicated table for logging.
The third way may seem impractical, as any errors will undo the insert in the log. This is the default behavior but can be circumvented.
MyLogTable log;
Connection con = new UserConnection();
con.ttsBegin();
log.setConnection(con);
... // Set your fields
log.insert();
con.ttsCommit();
Your way to go depends on circumstances you do not mention.
I can't catch the thrown error in my simplified code below. Why is that?
According to requirements of the stackoverflow I must insert some more info but this example is very simple. Can you help me with this example?
package com.myserver {
public class ReturnInfo extends Sprite {
public function ReturnInfo(urlParamsArr:Array) {
try {
var client:HttpClient = new HttpClient();
var uri:URI = new URI("http://valid-url.com/aaa.php");
client.listener.onData = function(event:HttpDataEvent):void {
throw new Error();
};
client.listener.onError = function(event:IOErrorEvent):void {
trace("error");
};
client.postFormData(uri, variables);
}
catch (e:Error){
trace("Error was caught.");
}
}
} //class
} //package
I tried also:
try {
new ReturnInfo(urlParamsArr);
}
catch(e:Error){
trace("caught error");
}
It didn't work either.
The code does not work because the code that throws error is executed later, so you need to use try-catch in the client.listener.onData handler. That handler I assume is called sometimes later so there when you parse or handle the data,make sure to catch/handle the errors
Adding on to what Simion said, the problem is method closure. In order for an exception to be caught somewhere in the "food chain" the catch needs to be in the stack - you will know what is in the current stack by getStackTrace(). In this example, there is no stack pointer that sits at the constructor (or any method) like there is one for client.listener.onData - which is why the postFormData will execute. When the event is triggered it's stack pointer goes back to the origination point of what actually started the event trigger in the first place (not the method that declared it). This is also why the 2nd attempt was unsuccessful.
Add on to the fact that the FP executes discrete chunks in frames (think of this like a heap), anything that executes in the scope of the dispatchEvent will generally have a very small or no stack at all (eg the first stack pointer is usually the dispatcher itself - not a method that actually called it).
try-catch is best attempted within the same scope of a method.
A pseudo example:
function getOrCreateWidget():Widget {
var a:Widget;
try {
a = getWidet();
}
catch(e:TypeError) {
a = createNewWidget();
}
//finally can be debatable - most of us leave it off
//bc it executes anyway just as it would in the function scope.
finally {
a.property = 'foo';
}
return a;
}
If this isn't possible - a last ditch effort is to attach a listener to the loaderInfo.uncaughtErrorEvents. Generally associating this with the systemManager is the best option because the SM knows about every branch of the display tree right down to the root stage. It's neither good practice nor practical to assign all deviations in this method because a lot of context to the programmer is usually lost. It's more an "oh S#!) sorry user, our app just verped."
In flex, how to check if a variable exists? I have tried using
if (this['some_variable'] != undefined) {
//do something
}
There is a run time error saying the property some_variable does not exists. I have checked with null instead of undefined, still the same error.
please help.
[EDIT]
Based on the replies I have used this.hasOwnProperty('variable_name'). I found that its returning true if variable_name is a public but false if its private/protected. How to check for a private variable?
There are two ways for that:
if ("some_variable" in this) {
//do something
}
It uses in operator.
And:
if (this.hasOwnProperty("some_variable")) {
//do something
}
See documentation about hasOwnProperty().
What about getting information about private/protected properties the situation is that you can't get this info with the current state of Flash Player. The only possible way, I suppose, is some kind of runtime bytecode manipulation. But as far as I know nobody implemented it yet.
But I have a question about getting info about private/protected properties: for what purpose you need it? The nature of these properties/methods is you can't call them. Even if you know about their existence.
You can use
if (this. hasOwnProperty("some_variable")) {
//access the variable inside
}
if (this.hasOwnProperty('some_variable')) DO_IT_!()
Explanation:
this['some_variable'] tries to evaluate the value of the instance property some_variable. If there is no such a property, you will get this error.
To test if a property exists for a particular object use hasOwnProperty or wrap your condition in a try/catch block or use if ('some_variable' in this).
Usually you create an object property in a class file:
public class MyClass {
public var myProperty : String = "ich bin hier";
}
Then you refer to that property within the class:
trace (myProperty);
trace (this.myProperty);
Using the array syntax [] is also possible but will throw the error if the property is not defined.
trace (this['myProperty']);
And finally! If you declare your class to be dynamic you might use the array syntax even if the property does not exist.
public dynamic class MyClass {
public function MyClass() {
trace (this["never_declared_property"]);
}
}
I have a question about .Net CF 3.5 Reflection.I am invoking expected something method like this,
object n= instance.Type.GetMethod("DoSome"
).Invoke(instance.Instance,
new object[] { commandKeys }
);
commandKey is my parameter list, instance.Type and instance.Instance is not null.
Methods invokes normally but, when I set any property(belongs to which I am calling class) in "DoSome" method, property dont have a value(default value).
public class CSet:ITask
{
public void DoSome
{
SomeProperty=true;
OnTaskCompleted(this);
}
}
I am catching "OnTaskCompleted" delegate which contains "ITask" interface but like i said ITask SomeProperty has not my given value
Thx your answers.
You say that the "Methods invokes normally", but at the same time you claim that the code inside the method is not executed. How do you know that the method is invoked at all?
Are you sure that instance.Instace is the same instance you check SomeProperty on, and catch OnTaskCompleted from?