I'm trying to handle exceptions with AOP approach in my Spring/Swing Application and I couldn't make it work.
Main Class:
public class MainFrame extends JFrame {
private JPanel mainPanel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame frame = new MainFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MainFrame() {
initializeMainPanel();
}
private void initializeMainPanel() {
exitLabel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
throw new Exception("test");
}
});
}
}
Aspect Class:
#Aspect
public class AspectTest{
#AfterThrowing(pointcut = "execution(* com.test.MainFrame.*(..))", throwing = "ex")
public void logError(Exception ex) throws Throwable {
// ex.printStackTrace();
}
}
So, I throw an exception within my Mouse Listener and expect to catch it in my AspectTest class' AfterThrowing method but it does not work.
Can someone please help me to understand what I'm missing here?
#AfterThrowing cannot catch exceptions, only notice them and log them or do something similar. If you want to handle exceptions in an aspect you need to use an #Around advice.
Related
Actually I am working in a Kafka streams application using Spring Boot.
So here I am trying to handle exceptions globally using #ControllerAdvice but it is not working for me.
Is it possible to use #ControllerAdvice in my application.
Is this controller advice is only works when the error is coming from controller.
Note: I am not having any controller / rest controller endpoints in my application.
Can we achieve the same in some other ways?
Please share your valuable thoughts!
Main Stream:
#Autowired
private XyzTransformer xyztransformer;
#Bean
public KStream<String, ABC> processMember(#Qualifier("defaultKafkaStreamsBuilder") StreamsBuilder streamsBuilder) {
try {
LOGGER.info("streaming started...");
KStream<String, Xyz> xyStream = streamsBuilder.stream(appProperty.kafkaStreamsTopicInput)
.transformValues(() -> xyztransformer)
xyStream.to(appProperty.kafkaStreamsTopicOutput);
return memberStream;
} catch (Exception ex) {
LOGGER.error("Exception occurred in Streams " + Arrays.toString(ex.getStackTrace()));
throw ex;
}
}
TransformerClass:
#Component
public class XyzTransformer implements ValueTransformer<Xyz, Abc> {
#Override
public void close() {
}
#Override
public void init(ProcessorContext processorContext) {
}
#SneakyThrows
#Override
public Abc transform(Xyz data) {
String[] dataSourceTables = new String[]{"abc"};
try {
return Abc.builder()
.name(data.getName())
.build();
} catch (Exception ex) {
System.out.println("catched and throwing");
throw new CustomTesException("test 1");
}
}
}
ControllerAdvice:
#ControllerAdvice
public class Advice extends ResponseEntityExceptionHandler {
#ExceptionHandler(NullPointerException.class)
public final void handleAllExceptions(NullPointerException ex) {
System.out.println("it is in the handler");
System.out.println(ex.getMessage());
}
#ExceptionHandler(Exception.class)
public final void handleAllException(Exception ex) {
System.out.println("it is in the exception handler");
System.out.println(ex.getMessage());
}
#ExceptionHandler(CustomTesException.class)
public final void handleAllExceptio(CustomTesException ex) {
System.out.println("it is in the exception handler");
System.out.println(ex.getMessage());
}
}
I am trying to connect to websocket server endpoint using below code but I am not able to resolve container.connectToServer(this, cec, uri); this. This method is not able to take my class as Endpoint class. It's a spring boot project. If I don't pass config then it accepts but then it fails to connect to server and return 401. I have tried many online links but failed to resolve this issue. Need help in how to fix it.
#ClientEndpoint
public class TestClassEndpoint {
private Session userSession = null;
public TestClassEndpoint(URI uri) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
ClientEndpointConfig cec = ClientEndpointConfig.Builder
.create().configurator(new ClientEndpointConfig.Configurator() {
public void beforeRequest(Map<String, List<String>> headers) {
System.out.println("Setting user cookie in beforeRequest ...");
headers.put("Authorization", Arrays.asList("Basic base64encodedString"));
}
}).build();
container.connectToServer(this, cec, uri);
} catch (Exception e) {
e.printStackTrace();
}
}
#OnOpen
public void onOpen(Session session) {
this.userSession = session;
System.out.println("New connection established");
}
#OnMessage
public void onMessage(String message, Session session) {
System.out.println(message);
}
#OnClose
public void onClose(Session userSession, CloseReason reason) {
this.userSession = null;
System.out.println("connection closed");
}
#OnError
public void onError(Throwable t) {
}
private void sendMessage(ByteBuffer buffer) {
this.userSession.getAsyncRemote().sendBinary(buffer);
}
}
Main class
#SpringBootApplication
public class MainApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(TwilioPocApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
URI uri = UriComponentsBuilder.fromUriString("server_url").build().toUri();
new TestClassEndpoint(uri);
}
}
What I want is to have an aspect around all methods annotated with #RabbitHandler so that AssertionErrors won't kill the handler thread.
I just want to wrap them inside RuntimeExceptions and rethrow.
Motivation: there is additional error handling that I want to use which works well except for these AssertionErrors.
I could add a try-catch for AssertionErrors in each method but there are too many places and instead I was thinking of using aspects.
#Aspect
public class RabbitAssertionErrorHandlerAspect {
#Around("#annotation(org.springframework.amqp.rabbit.annotation.RabbitHandler)")
public Object intercept(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (AssertionError e) {
throw new RuntimeException(e);
}
}
}
All nice and elegant but it doesn't get called. I assume this has something to do with the way these methods are discovered in the first place.
Any reasonable workarounds anyone sees?
The #RabbitListener on the class with those #RabbitHandlers can be configured with:
/**
* Set an {#link org.springframework.amqp.rabbit.listener.RabbitListenerErrorHandler}
* to invoke if the listener method throws an exception.
* #return the error handler.
* #since 2.0
*/
String errorHandler() default "";
So, consider to go the custom RabbitListenerErrorHandler way instead.
It works with Spring AOP...
#SpringBootApplication
public class So48324210Application {
public static void main(String[] args) {
SpringApplication.run(So48324210Application.class, args);
}
#Bean
public MethodInterceptor interceptor() {
return i -> {
try {
System.out.println("here");
return i.proceed();
}
catch (AssertionError e) {
throw new RuntimeException(e);
}
};
}
#Bean
public static BeanNameAutoProxyCreator proxyCreator() {
BeanNameAutoProxyCreator pc = new BeanNameAutoProxyCreator();
pc.setBeanNames("foo");
pc.setInterceptorNames("interceptor");
return pc;
}
#Bean
public Foo foo() {
return new Foo();
}
public static class Foo {
#RabbitListener(queues = "one")
public void listen(Object in) {
System.out.println(in);
}
}
}
or, as Artem said, a custom error handler will work too.
I'm having a hard time to work with jersey test framework.
I have a root resource.
#Path("sample")
public class SampleResource {
#GET
#Path("path")
#Produces({MediaType.TEXT_PLAIN})
public String readPath() {
return String.valueOf(path);
}
#Inject
private java.nio.file.Path path;
}
I prepared a factory providing the path.
public class SamplePathFactory implements Factory<Path> {
#Override
public Path provide() {
try {
return Files.createTempDirectory(null);
} catch (final IOException ioe) {
throw new RuntimeException(ioe);
}
}
#Override
public void dispose(final Path instance) {
try {
Files.delete(instance);
} catch (final IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
And a binder.
public class SamplePathBinder extends AbstractBinder {
#Override
protected void configure() {
bindFactory(SamplePathFactory.class).to(Path.class);
}
}
And, finally, my test class.
public class SampleResourceTest extends ContainerPerClassTest {
#Override
protected Application configure() {
final ResourceConfig resourceConfig
= new ResourceConfig(SampleResource.class);
resourceConfig.register(SamplePathBinder.class);
return resourceConfig;
}
}
When I tried to test, I got.
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=Path,parent=SampleResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1916953383)
What did I do wrong?
Your AbstractBinders should be registered as an instance, not as a class. So make the change
resourceConfig.register(new SamplePathBinder());
and it should work
I am trying to get my Blackberry application to display a custom modal dialog, and have the opening thread wait until the user closes the dialog screen.
final Screen dialog = new FullScreen();
...// Fields are added to dialog
Application.getApplication().invokeAndWait(new Runnable()
{
public void run()
{
Application.getUiApplication().pushModalScreen(dialog);
}
});
This is throwing an Exception which says "pushModalScreen called by a non-event thread" despite the fact that I am using invokeAndWait to call pushModalScreen from the event thread.
Any ideas about what the real problem is?
Here is the code to duplicate this problem:
package com.test;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
public class Application extends UiApplication {
public static void main(String[] args)
{
new Application();
}
private Application()
{
new Thread()
{
public void run()
{
Application.this.enterEventDispatcher();
}
}.start();
final Screen dialog = new FullScreen();
final ButtonField closeButton = new ButtonField("Close Dialog");
closeButton.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
Application.getUiApplication().popScreen(dialog);
}
});
dialog.add(closeButton);
Application.getApplication().invokeAndWait(new Runnable()
{
public void run()
{
try
{
Application.getUiApplication().pushModalScreen(dialog);
}
catch (Exception e)
{
// To see the Exception in the debugger
throw new RuntimeException(e.getMessage());
}
}
});
System.exit(0);
}
}
I am using Component Package version 4.5.0.
Building on Max Gontar's observation that the Exception is not thrown when using invokeLater instead of invokeAndWait, the full solution is to implement invokeAndWait correctly out of invokeLater and Java's synchronization methods:
public static void invokeAndWait(final Application application,
final Runnable runnable)
{
final Object syncEvent = new Object();
synchronized(syncEvent)
{
application.invokeLater(new Runnable()
{
public void run()
{
runnable.run();
synchronized(syncEvent)
{
syncEvent.notify();
}
}
});
try
{
syncEvent.wait();
}
catch (InterruptedException e)
{
// This should not happen
throw new RuntimeException(e.getMessage());
}
}
}
Unfortunately, the invokeAndWait method cannot be overridden, so care must be used to call this static version instead.
Seems as though there's a bunch of code in there that's unnecessary.
public class Application extends UiApplication {
public static void main(String[] args)
{
new Application().enterEventDispatcher();
}
private Application()
{
final Screen dialog = new FullScreen();
final ButtonField closeButton = new ButtonField("Close Dialog");
closeButton.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
Application.getUiApplication().popScreen(dialog);
}
});
dialog.add(closeButton);
// this call will block the current event thread
pushModalScreen(dialog);
System.exit(0);
}
}
Use this:
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
pushScreen(new MyScreen());
}
});