Why is Guava issuing the error "missing event handler for an > annotated method"? - guava

I'm getting the following error in one of my classes on the when attempting to unregister it.
java.lang.IllegalArgumentException: missing event handler for an
annotated method. Is
[DerivedClass] registered?"
at com.google.common.eventbus.EventBus.unregister(EventBus.java:227)
The class calling unregister(this) has the public #Subscribe annotated method.

The problem was that the error message misled me to think there was something wrong with the annotations. It was in fact that the class was unregistering itself twice due to some unexpected flow of control.

A source code explanation:
/**
* Unregisters all handler methods on a registered {#code object}.
*
* #param object object whose handler methods should be unregistered.
* #throws IllegalArgumentException if the object was not previously registered.
*/
public void unregister(Object object) {
Multimap<Class<?>, EventHandler> methodsInListener = finder.findAllHandlers(object);
for (Entry<Class<?>, Collection<EventHandler>> entry : methodsInListener.asMap().entrySet()) {
Class<?> eventType = entry.getKey();
Collection<EventHandler> eventMethodsInListener = entry.getValue();
handlersByTypeLock.writeLock().lock();
try {
Set<EventHandler> currentHandlers = handlersByType.get(eventType);
if (!currentHandlers.containsAll(eventMethodsInListener)) {
throw new IllegalArgumentException(
"missing event handler for an annotated method. Is " + object + " registered?");
}
currentHandlers.removeAll(eventMethodsInListener);
} finally {
handlersByTypeLock.writeLock().unlock();
}
}
}

Related

Redirect if request authorization is failed in Laravel 5.5

I am trying to redirect request if authorization is failed for it. I have following code:
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){ /* ... */}
public function failedAuthorization() {
return redirect('safepage');
}
}
By default I am redirected to the 403 error page, but I would like to specify some specific route. I noticed that method failedAuthorization() is run, but redirect() method does not work...
Previously this code worked well with Laravel 5.1 but I used forbiddenResponse() method to redirect wrong request. How can I fix it with new LTS version?
Looks like it is impossible to redirect() directly from the custom ValidateRequest class. The only solution that I found is create custom exception and than handle it in the Handler class. So, now it works with following code:
Update: The method redirectTo() was updated to make solution work on Laravel 6.x and higher
app/Requests/ValidateRequest.php
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){
return [];
}
public function failedAuthorization() {
$exception = new NotAuthorizedException('This action is unauthorized.', 403);
throw $exception->redirectTo("safepage");
}
}
app/Exceptions/NotAuthorizedException.php
<?php
namespace App\Exceptions;
use Exception;
class NotAuthorizedException extends Exception
{
protected $route;
public function redirectTo($route) {
$this->route = $route;
abort(Redirect::to($route));
}
public function route() {
return $this->route;
}
}
and app/Exceptions/Handler.php
...
public function render($request, Exception $exception){
...
if($exception instanceof NotAuthorizedException){
return redirect($exception->route());
}
...
}
So, it works, but much more slower than I expected... Simple measuring shows that handling and redirecting take 2.1 s, but with Laravel 5.1 the same action (and the same code) takes only 0.3 s
Adding NotAuthorizedException::class to the $dontReport property does not help at all...
Update
It runs much more faster with php 7.2, it takes 0.7 s
If you are revisiting this thread because in 2021 you are looking to redirect after failed authorization here's what you can do:
You cannot redirect from the failedAuthorization() method because it is expected to throw an exception (check the method in the base FormRequest class that you extend), the side effect of changing the return type is the $request hitting the controller instead of being handled on FormRequest authorization level.
You do not need to create a custom exception class, neither meddle with the Laravel core files like editing the render() of app/Exceptions/Handler.php, which will pick up the exception you threw and by default render the bland 403 page.
All you need to do is throw new HttpResponseException()
In the Laravel reference API we can see its job is to "Create a new HTTP response exception instance." and that is exactly what we want, right?
So we need to pass this Exception a $response. We can pass a redirect or JSON response!
Redirecting:
protected function failedAuthorization()
{
throw new HttpResponseException(response()->redirectToRoute('postOverview')
->with(['error' => 'This action is not authorized!']));
}
So we are creating a new instance of the HttpResponseException and we use the response() helper, which has this super helpful redirectToRoute('routeName') method, which we can further chain with the well known with() method and pass an error message to display on the front-end.
JSON:
Inspired by this topic
throw new HttpResponseException(response()->json(['error' => 'Unauthorized action!'], 403));
Thats'it.
You don't have to make ANY checks for validation or authorization in your controller, everything is done in the background before it hits the controller. You can test this by putting a dd('reached controller'); at the top of your controller method and it shouln't get trigered.
This way you keep your controller thin and separate concerns :)
Sidenote:
forbiddenResponse() has been replaced after lara 5.4 with failedAuthorization()
You can do through a middleware/policy i think. I don't know if you can do it from the validation.
You can override the function from FormRequest like this below:
/**
* Handle a failed authorization attempt.
*
* #return void
*
* #throws \Illuminate\Auth\Access\AuthorizationException
*/
protected function failedAuthorization()
{
throw new AuthorizationException('This action is unauthorized.');
}
And redirect where you want.

using Class<?> to represent an interface

I hope the title accurately represents what I'm asking here. For my assignment here, I have a Speakerphone object, which is a singleton, and two interfaces, Listener and Talker with which Speakerphone needs to communicate.
There are two shoutMessage methods, the second of which takes a Class object as a parameter. Here's where I'm confused - I don't know if the "Class object" in the instructions is referring to the Listener interface, or the Speakerphone object. Can anyone tell me if the code in this method is correct, based on the instructions here?
public class Speakerphone extends Object {
private static Speakerphone sSpeaker = null;
private static HashSet<Listener> mListener = new HashSet<Listener>();
private static HashSet<Talker> mTalker = new HashSet<Talker>();
private Speakerphone() {
}
/*
* get
*
* #return the singleton instance of Speakerphone (Speakerphone)
*/
/************************************************
* ASSIGNMENT:
* Implement the get method
/************************************************/
public static Speakerphone get(){
if (sSpeaker == null){
sSpeaker = new Speakerphone();
}
return sSpeaker;
}
/*
* shoutMessage
*
* Sends the message to all of the Listeners tracked by Speakerphone
*
* #param talker a Talker whose message will be sent (Talker)
* #return nothing
*/
/************************************************
* ASSIGNMENT:
* Implement the shoutMessage method
/************************************************/
public void shoutMessage(Talker talker){
Iterator<Talker> talkIterator = mTalker.iterator();
while(talkIterator.hasNext())
talkIterator.next().getMessage();
}
/*
* shoutMessage
*
* Sends the message to all of the Listeners which are instances of
* the cls parameter
*
* #param talker a Talker whose message will be sent (Talker)
* #param cls a Class object representing the type which the Listener
* should extend from in order to receive the message (Class)
* #return nothing
*
* HINT: see Class.isAssignableFrom()
* http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class)
*/
/************************************************
* ASSIGNMENT:
* Implement the shoutMessage method
/************************************************/
public void shoutMessage(Talker talker, Class<?> cls){
if (Listener.class.isAssignableFrom(cls)){
Iterator<Talker> talkIterator = mTalker.iterator();
while(talkIterator.hasNext())
talkIterator.next().getMessage();
}
}
}
So, the class parameter in the shoutMessage method appears to be there so you can select out only listeners of a certain type. Class in Java is an object that describes a data type - a meta of meta so to speak.
Based on the comments in the code it looks like your shoutMessage method might be doing the opposite of what you want. Here's what I think it needs to do (based on the comments of the method):
Iterate through all of the listeners in your mListener HashSet. For each listener in the HashSet, do the following
As you iterate through, use Listener.class.isAssignableFrom to determine if the current listener is of class cls.
If it is of the type cls then call talker.getMessage() and pass that message to the current listener (by calling "receiveMessage" or "on" or whatever function is defined in your Listener interface).
If it is not of the type cls then ignore.

Symfony2 - Forced to validate inside DataTransformer because of type hint on setter

I have created an Object to ID Data Transformer. It's part of a custom ObjectIdType that allows me to enter the ID of a document instead of using a 'document' form type. It's handy for MongoDB (when there could be 100 million documents to choose from).
The Data Transformer does a query upon the ID and returns an object. If it can't find an object then it returns null. The issue is - sometimes null is an acceptable value, and sometimes it isn't.
Even if I add a NotNull validator, I get the following error -
Catchable Fatal Error: Argument 1 passed to Character::setPlayer() must be an instance of Document\Player, null given
So it's calling the setter regardless of the validation failing. I fixed this by throwing a TransformationFailedException within the transformer - but this just seems like a bad idea. I shouldn't really be using a Data Transformer to validate.
The code of the transformer is below. What I'd like is to be able to put the validator in the correct place, and intercept the setter so it doesn't get called. Generally, this seems like a bit of a code smell, I would love to know how other people have solved this issue.
class ObjectToIdTransformer implements DataTransformerInterface
{
private $objectLocator;
private $objectName;
private $optional;
/**
* #param ObjectLocator $objectLocator
* #param $objectName
*/
public function __construct(ObjectLocator $objectLocator, $objectName, $optional = false)
{
$this->objectLocator = $objectLocator;
$this->objectName = $objectName;
$this->optional = $optional;
}
/**
* {#inheritdoc}
*/
public function transform($value)
{
if (null === $value) {
return null;
}
if (!$value instanceof BaseObject) {
throw new TransformationFailedException("transform() expects an instance of BaseObject.");
}
return $value->getId();
}
/**
* {#inheritdoc}
*/
public function reverseTransform($value)
{
if (null === $value) {
return null;
}
$repo = $this->objectLocator->getRepository($this->objectName);
$object = $repo->find($value);
if (!$this->optional && !$object) {
throw new TransformationFailedException("This is probably a bad place to validate data.");
}
return $object;
}
}
Actually, it's a PHP quirk that's very unintuitive — especially for those coming from other (logical, intuitive, sane) languages like Java. If you want to be able to pass a null argument to a typehinted parameter, you have to set its default value to null:
public function setPlayer(Player $player = null)
{
// ...
}
Yea, talk about some consistency here...

Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event: 'prePersist'

I created an EJB Session facade in my Netbeans 7 for saving my entity.
I have a manytoone mapping between my Insurance and RatePlan Class.
public class Insurance{
#ManyToOne(optional=false)
#JoinColumn(name="PLAN_ID")
private RatePlan plan;
}
public class RatePlan{
#OneToMany(mappedBy="plan")
private Set<Insurance> insuranceItems;
}
When I tried saving in my database using my EJB Session Bean, I am encountering below error.
Caused by: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.
What I did was to turn off my Bean validation in my Persistence.xml file.
I would like to know what Bean validation error has occurred but I dont know how or where to find it or how to configure and catch it.
My EJB facade is a simple class like tis.
public class InsuranceFacade{
public void saveInsurance(Insurance insurance){
em.persist(insurance);
}
}
Any hints?
I would like to know what Bean validation error has occurred but I dont know how or where to find it or how to configure and catch it.
To know what specific constraint violations have occurred, you could just inspect the exception caught. ConstraintViolationException.getConstraintViolations() returns a Set of ConstraintViolations which you can iterate and inspect.
I got the same problem, but after hours looking for the answer, Finally I Found it.... You should edit your AbstractFacade.java class and add this code
public void create(T entity) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity);
if(constraintViolations.size() > 0){
Iterator<ConstraintViolation<T>> iterator = constraintViolations.iterator();
while(iterator.hasNext()){
ConstraintViolation<T> cv = iterator.next();
System.err.println(cv.getRootBeanClass().getName()+"."+cv.getPropertyPath() + " " +cv.getMessage());
JsfUtil.addErrorMessage(cv.getRootBeanClass().getSimpleName()+"."+cv.getPropertyPath() + " " +cv.getMessage());
}
}else{
getEntityManager().persist(entity);
}
}
Now this method will alert you which property and why it fails the validation.
I hope this works for you, as it does for me.
catch (EJBException e) {
#SuppressWarnings("ThrowableResultIgnored")
Exception cause = e.getCausedByException();
if (cause instanceof ConstraintViolationException) {
#SuppressWarnings("ThrowableResultIgnored")
ConstraintViolationException cve = (ConstraintViolationException) e.getCausedByException();
for (Iterator<ConstraintViolation<?>> it = cve.getConstraintViolations().iterator(); it.hasNext();) {
ConstraintViolation<? extends Object> v = it.next();
System.err.println(v);
System.err.println("==>>"+v.getMessage());
}
}
Assert.fail("ejb exception");
}
Catch the following exception where you persisting the entity. In my case its in the EJB add method. where I am doing em.persist(). Then check the server log, you will see which attribute having constrain violation.
catch (ConstraintViolationException e) {
log.log(Level.SEVERE,"Exception: ");
e.getConstraintViolations().forEach(err->log.log(Level.SEVERE,err.toString()));
}

How to trigger onFailure in GWT RPC? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
StatusCodeException Vs. RuntimeException in GWT
I want to trigger RPC callback "onFailure" if the session expires in the server.
I created a custom RPC AsyncCallback that handles the "session expired" event from the server.
I overrode RemoteServiceServlet to validate the session prior to invoking the method. So basically, it is not the declared method that throws the exception but the custom RemoteServiceServlet. It still goes to the "onFailure" in the client async but the Throwable object is still of type "StatusCodeException" without the EXPIRED_SESSION_MSG message. Any ideas?
Custom RemoteServiceServlet:
public class XRemoteServiceServlet extends RemoteServiceServlet {
private final static String EXPIRED_SESSION_MSG = "ERROR: Application has expired session.";
#Override
protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
HttpSession session = httpServletRequest.getSession(false);
if (session != null) {
final String sessionIdFromRequestHeader = getSessionIdFromHeader();
if (!isNullOrEmptyString(sessionIdFromRequestHeader)) {
final String sessionId = session.getId();
if (!sessionId.equals(sessionIdFromRequestHeader)) {
throw new RuntimeException(EXPIRED_SESSION_MSG);
}
}
Custom AsyncCallback:
public class XAsyncCallback<T> implements AsyncCallback<T> {
private final static String EXPIRED_SESSION_MSG = "ERROR: Application has expired session.";
#Override
public void onFailure(Throwable caught) {
final String message = caught.getMessage();
if (!isNullOrEmptyString(message) && message.contains(EXPIRED_SESSION_MSG)) {
com.google.gwt.user.client.Window.Location.reload();
}
}
#Override
public void onSuccess(T arg0) {
}
/**
* Returns true if the string is null or equals to the empty string.
*
* #param string the string to test
* #return true if the string is empty
*/
private static boolean isNullOrEmptyString(String string) {
return string == null || "".equals(string);
}
}
See here for handling exceptions with GWT RPC.
An "expected failure" is an exception thrown by a service method that is declared in the signature of the service method. These exceptions are serialized back to the client.
"Unexpected expections" are errors that are not part of the service method's signature, or that result from SecurityExceptions, SerializationExceptions, or other failures within the RPC framework.
What you want is a checked exception, because you want to send it back to the client and do something about it. The RPC framework is in charge of catching it, serializing it and calling the onFailure method with the right exception. In order to do that, you need to follow its guidelines which are :
You need to specifiy in the service
signature that the exception can be
thrown.
The exception must be thrown
in the service implementation method.
What you're doing is throwing an unexcepted exception from some method that shouldn't even be throwing exceptions. So RPC doesn't know what really happened and sends back a generic message saying 'Hey, something unexpected happened, look at the server log'.
I understand that you want to check the session on every call. Your easiest option is to have a method to check that in your servlet implementation and call it from all your service methods.
Otherwise, you can try to override the GWT RPC framework by looking at the class
com.google.gwt.user.server.rpc.RPC
but that's pretty advanced stuff.
If you want to send exceptions via GWT-RPC you must use checked exceptions. RuntimeException is an unchecked exception so you can not use it in this case.
Create your own exception that extends Exception and implements Serializable. Also, you must indicate on methods declaration that this method might throw an exceptions: