How to add Global Exception Handling on RouteTemplate - spring-camel

I am looking for a way to add global exception handling on all routes generated by multiple RouteTemplates. I have tried the following way but the onException block is not getting added to the routes.
Can you help me understand what I am doing wrong?
Thanks
public abstract class BaseRouteBuilder extends RouteBuilder {
#Override
public void configure(){
this.onException(IllegalStateException.class)
.log("global onException")
.maximumRedeliveries(2)
.redeliveryDelay(100)
.logStackTrace(true)
.to("direct:retryChannel");
}
}
public static class SampleRouteTemplate extends BaseRouteBuilder {
#Override
public void configure() {
super.configure();
this.routeTemplate("myTemplate")
.templateParameter("parameter1")
.from("direct:start")
.setHeader("parameter1", constant("value1"))
.log("RouteCompleted");
}
}

Try to extract a separate method for route, e.g. configureRoute() and call it in parent class in configure() method. Also make a child class non-static.
public abstract class BaseRouteBuilder extends RouteBuilder {
#Override
public final void configure(){
onException(IllegalStateException.class)
.log("global onException")
.maximumRedeliveries(2)
.redeliveryDelay(100)
.logStackTrace(true)
.to("direct:retryChannel");
configureRoute();
}
public abstract void configureRoute();
}
public class SampleRouteTemplate extends BaseRouteBuilder {
#Override
public void configureRoute() {
this.routeTemplate("myTemplate")
.templateParameter("parameter1")
.from("direct:start")
.setHeader("parameter1", constant("value1"))
.log("RouteCompleted");
}
}
}

Related

Creating a global interceptor for all defined routes

I have multiple route builders within my project,
I want to define a single interceptSendToEndpoint that will affect all of the defined routes
For Example:
Public Route1 extends RouteBuilder {
public void configure() throws Exception {
from("direct:endpoint1").toD("http:\\someAddress1");
}
}
Public Route2 extends RouteBuilder {
public void configure() throws Exception {
from("direct:endpoint2").toD("http:\\someAddress2");
}
}
what I want to do here is to define a central interceptSendToEndpoint that will automatically capture all traffic sent to the camel HTTP component for all routes.
public class InterceptRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
interceptSendToEndpoint("http:*")
.process(exchange -> System.out.println("Hi from intercept"));
}
}
However due to how camel injects the intercept scope, I'm unable to do this easily,
Is there a way to tell the camel context that this intercept is for all defined routes within the context?
Note: I'm using camel 3.0.0
Camel team works for similar task in there (https://issues.apache.org/jira/projects/CAMEL/issues/CAMEL-16757?filter=allissues&orderby=cf%5B12310200%5D+ASC%2C+priority+DESC%2C+updated+DESC).
Create an abstract base class and define your in there and then extends it in main route
public abstract class BaseRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
interceptSendToEndpoint("http:*")
.process(exchange -> System.out.println("Hi from intercept"));
}
}
public class TaskRoute2 extends BaseRoute {
#Override
public void configure() throws Exception {
super.configure();
from("direct:endpoint2").toD("http:\\someAddress2");
}
}
public class TaskRoute2 extends BaseRoute {
#Override
public void configure() throws Exception {
super.configure();
from("direct:endpoint2").toD("http:\\someAddress2");
}
}

How to access or grant based on custom conditions

Assume i want to grant an user based on certain conditions not based on roles or permissions or anything.
Assume a user hits the url /getAllOrders. i need to give access if satisfies certain conditions.
In that case, i am not sure how to do it. I checked and come across AccessDecisionVoter and not sure whether it will be suitable for it and also don't know how to implement it.
can someone suggest whethere AccessDecisionVoter would be the right option ?
looking for working sample code snippet which uses AccessDecisionVoter
Thanks.
In your controller you can make use of #PreAuthorize on your handler method and call a method that you declare inside a subclass of SecurityExpressionRoot. You need to do a bit of configuration to register your SecurityExpressionRootinside of a GlobalMethodSecurityConfiguration
In your Controller:
#PreAuthorize("isMyCustomConditionMet()")
#GetMapping("/getAllOrders")
public String allOrders(Model model) {
model.addAttribute("orders", orderService.getAllOrders());
return "orders";
}
In a configuration class:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class CustomMethodSecurityConfig extends
GlobalMethodSecurityConfiguration {
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new CustomMethodSecurityExpressionHandler();
}
}
This is the class we are instantiating above:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
#Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation methodInvocation) {
CustomSecurityExpressionRoot root = new CustomSecurityExpressionRoot(authentication);
root.setThis(methodInvocation.getThis());
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(new AuthenticationTrustResolverImpl());
root.setRoleHierarchy(getRoleHierarchy());
root.setDefaultRolePrefix("ROLE_");
return root;
}
}
This is where you define your customer logic:
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot
implements MethodSecurityExpressionOperations {
private Object filterObject;
private Object returnObject;
private Object target;
public CustomSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
public boolean isMyCustomConditionMet() {
return [INSERT YOUR LOGIC HERE!];
}
#Override
public void setFilterObject(Object filterObject) {
this.filterObject = filterObject;
}
#Override
public Object getFilterObject() {
return filterObject;
}
#Override
public void setReturnObject(Object returnObject) {
this.returnObject = returnObject;
}
#Override
public Object getReturnObject() {
return returnObject;
}
void setThis(Object target) {
this.target = target;
}
#Override
public Object getThis() {
return target;
}
}

Injecting objects created via hk2+jersey returns null

I have the following resource class
#Path("/helloworld")
public class HelloWorldResource {
#Inject
private UserAuthorizationRepository userRepository;
#GET
public Response sayHello(#Context UriInfo uriInfo)
Following is my implementation of UserAuthorizationRepository
public class UserAuthorizationRepositoryImpl implements UserAuthorizationRepository {
#Inject
private MyUserIdToUserNameTable userIdToUserNameTable;
public String getUserName(Long userId) {
userNameToUserIdTable.getUserName(userId)
}
and I have register the following binder to the ResourceConfig
public class RepositoryBinder extends AbstractBinder {
#Override
protected void configure() {
bind(new UserAuthorizationRepositoryImpl()).to(UserAuthorizationRepository.class);
bind(new MyUserIdToUserNameTable()).to(UserIdToUserNameTable.class);
}
After this, the userRepository in my resource class is binding correctly, however, the userIdToUserNameTable in the UserAuthorizationRepositoryImpl is null.
Does anyone know the reason? Thank you in advance!
For one thing, it looks like you are creating the UserAuthorizationRepositoryImpl yourself rather than letting hk2/Jersey create it. You might want to instead try:
public class RepositoryBinder extends AbstractBinder {
#Override
protected void configure() {
bind(UserAuthorizationRepositoryImpl.class).to(UserAuthorizationRepository.class);
bind(MyUserIdToUserNameTable.class).to(UserIdToUserNameTable.class);
}
That will allow hk2/Jersey to create the classes, and properly inject them.

cannot find symbol on getApplication() on AsyncTask

I am using AsyncTask and want to use getApplication() to work with class Application.
But gets error on getApplication() cannot find symbol.
my code:
public class splash extends AsyncTask {
protected config app;
public splash(Context context) {
super();
app = ((config) getApplication());
this.context=context;
}
and the class that I want to use:
public class config extends Application
{
public Boolean con=true;
public int status=-1;
public String actNum;
public void onCreate()
{
super.onCreate();
}
}
If you want to get the Application instance, you can initialize a member in onCreate() with it and have it returned by a class method:
public class ApplicationConfig extends Application {
private static ApplicationConfig instance;
public void onCreate() {
super.onCreate();
instance = this;
}
public static ApplicationConfig getConfig() {
return instance;
}
}
Then you can retrieve this instance everywhere via:
ApplicationConfig conf = ApplicationConfig.getConfig();

how to bundle handlers in the handlerManager?

is there a option to bundle different eventhandler in one javafile?
Like:
public interface MyHandlerr extends EventHandler {
void myEvent1(Event1 event);
void myEvent2(Event2 event);
}
in the moment i have for each event one handler....but i'm not happy with it.
greetz
You can create your own EventHandler interface for handling multiple events
public interface MultipleEventsHandler extends EventHandler {
void onMyEvent(MyEvent event);
void onMyOtherEvent(MyOtherEvent event);
}
Then in your event classes you can define which of the methods should be called
public class MyEvent extends GwtEvent<MultipleEventsHandler> {
public static final Type<MultipleEventsHandler> TYPE = new Type<MultipleEventsHandler>();
#Override
public Type<MultipleEventsHandler> getAssociatedType() {
return TYPE;
}
#Override
protected void dispatch(MultipleEventsHandler handler) {
handler.onMyEvent(this);
}
}
public class MyOtherEvent extends GwtEvent<MultipleEventsHandler> {
public static final Type<MultipleEventsHandler> TYPE = new Type<MultipleEventsHandler>();
#Override
public Type<MultipleEventsHandler> getAssociatedType() {
return TYPE;
}
#Override
protected void dispatch(MultipleEventsHandler handler) {
handler.onMyOtherEvent(this);
}
}
If you just want to reduce number of classes/interfaces then you can put EventHandler's inside your event classes, e.g.
public class MyEvent extends GwtEvent<MyEvent.Handler> {
public interface Handler extends EventHandler {
void onMyEvent(SomeEvent event);
}
public static final Type<MyEvent.Handler> TYPE = new Type<MyEvent.Handler>();
#Override
public Type<MyEvent.Handler> getAssociatedType() {
return TYPE;
}
#Override
protected void dispatch(MyEvent.Handler handler) {
handler.onMyOtherEvent(this);
}
}

Resources