Spring Integration's Gateway element has a "default-reply-timeout" attribute, but no way to set the timeout value based on data from the message itself. I can create a gateway for each possible timeout value and then select an appropriate gateway for that message during run-time, but that's obviously a nasty workaround.
Release 4.2 added a "remote-timeout-expression" attribute to TCPOutboundGateway, but that change didn't make it to the GatewayProxyFactoryBean.
That being said, is there a way to configure timeouts on a message-specific basis? If not, Is the "remote-timeout-expression" attribute planning on being ported to the GatewayProxyFactoryBean at some point?
Thanks for any help!
It's currently a fixed value and not configurable on a message-by-message basis.
We can certainly consider making it so but it would likely not make it into 4.3, since the release candidate is already out.
One possible work-around would be use MessagingTemplates instead of a gateway. You could set up a collection of MessagingTemplates, each configured with a different timeout, instead of the gateway:
Foo result = this.templateWith10SecondTimeout.convertSendAndReceive(bar, Foo.class);
Alternatively, you can add different methods to your gateway, each with a different reply timeout.
public interface GW {
Foo waitTenSeconds(Bar bar);
Foo waitTwentySeconds(Bar, bar);
}
The default timeout is a default, the timeout can be set on each method.
Related
I have started a few days ago to learn about fault tolerance solutions in microservices. I have some microservices in my ecosystem and they are now interconnected with Eureka service lookup. I used FeignClient to call from one to another. As I heard and read, that Hystrix is getting into maintenance, I wondered if I could use Resilience4J in Feign instead of Hystrix. Well, at least not from annotation level right now as it seems. I found a great Feign.Builder adapter to add resilience4j fault tolerance features above a FeignClient as a decorator (https://github.com/resilience4j/resilience4j/tree/master/resilience4j-feign) so I wanted to use it.
So I used this, added together the features and added the default encoder, decoder, etc. items into the feign builder. Turns out I have to finish of course my code with a .target call which creates my client proxy and I could not really do this with Eureka in a good way:
The first constructor, which takes the class type and the URL is hardcoded, so if I add an eureka next server query into this parameter, it is just a hardcoded url for one of the instances, this is not load balanced. Some kinda workaround could be that I create prototype-scope or similar short lived scoped beans of this client and always get the "next url" for the call. This adds lots of burden to use the clients in every class I make. At least as I saw it. Maybe I could add some kind of singleton helper bean around the prototyping, but again this is not a good design as I see
I thought maybe I could create an EurekaTarget from the Target interface, but of course none of the methods indicate any "end of lifecycle" things, not even the apply method. I thought maybe that is one point which is called before doing a service call, but I saw multiple calls towards it so I had to change the url for all calls.
Do you know any better solution to do this migration?
I guess you are using Spring Boot?
The next version v1.0.0 of Resilience4j will support the #FeignClient annotation.
There was a PR which added the functionality -> https://github.com/resilience4j/resilience4j/pull/579
You can then use it as follows:
#FeignClient(name = DUMMY_FEIGN_CLIENT_NAME)
#CircuitBreaker(name = DUMMY_FEIGN_CLIENT_NAME)
public interface DummyFeignClient {
String DUMMY_FEIGN_CLIENT_NAME = "dummyFeignClient";
#GetMapping(path = "/api/{param}")
void doSomething(#PathVariable(name = "param") String param);
}
I was trying to understand the caching that happens at the client side.
Unfortunately I am unable to find any resources that can help me out.
I have employee model objects which are fairly small in size.
Once a use a GET request to obtain an employee object, I want it to be cached at the client side
Now when the request comes again to obtain the same employee, I want to see if the actual object has been modified, if not, then serve from the client cache else return the modified object also adding it to the cache.
I am using Spring boot to create a REST endpoint.
What I have been able to figure out is that cache-control would be used some how, but I am not sure how the objects would be added here in spring.
Any help here is much appreciated!!!!
Thanks,
Amar
HTTP caching is not an easy topic. There are different ways to do it, and you should probably start by familiarizing yourself with the mechanisms, this seems to be a good starting resource: HTTP caching
Then, you will probably identify some common usage patterns you will want to reuse. One way to do that is to create custom annotations and write an interceptor that reacts on them.
For example, you could write such an annotation:
#Inherited
#Retention(RUNTIME)
#Target({METHOD, TYPE})
public #interface CacheFor {
long amount();
TimeUnit unit() default TimeUnit.SECONDS;
}
and use it on controller methods like this:
#CacheFor(amount=10, unit = MINUTES)
#RequestMapping(bla bla)
public FooBar serveMyData(){
// code here
}
and in your interceptor, you will need to look at the handler method, check whether it has this annotation, and if it does, set the appropriate headers.
I have enabled a server authentication module (JSR196) in Glassfish . The module works as expected however i need to determine the presence of the authentication module in a servlet programatically.
Is there any way i could check the presence of the authentication module using java ?
Dexter meyers' approach should work just fine, provided that:
your application uses a single ServerAuthModule (SAM),
no AS-wide -i.e. having been registered with the AuthConfigFactory with null appContext and "HttpServlet" or null layer arguments- AuthConfigProvider has been established,
you do not provide your own AuthConfigProvider, ServerAuthConfig and ServerAuthContext implementations, and
your sole concern is to receive a runtime confirmation that the SAM has been "activated" for your application.
Otherwise, a non-null return from AuthConfigFactory#getConfigProvider(String, String, RegistrationListener) might be misleading, in the sense that it does not necessarily assert that your application uses a SAM, only that an AuthConfigProvider has been put into place at a compatible layer and could serve your application's authentication needs if the rest of the required components (ServerAuthConfig et al.) are registered as well.
If you additionally need to know which SAMs exactly your application has been configured to use, there is, afaik, no standard way to do so, as, first and foremost, ServerAuthContext does not expose its encapsulated SAMs (and its very acquisition via ServerAuthConfig#getAuthContext(String, Subject, Map) is not straightforward anyway, since JASPIC's Servlet Profile leaves authContextIDs arbitrary). Which basically means you will either need to implement your own ServerAuthContext (along with the 2 further indirections) to get that functionality, or alternatively attach an identifier to represent the SAM to the HttpServletRequest or HttpSession, if it suffices for you to know which SAMs got triggered for individual requests. Note that in case you prefer to use the javax.servlet.http.authType MessageInfo callback property to set the value returned by HttpServletRequest#getAuthType() instead, it will only work when authentication succeeds, that is, when your SAM's validateRequest(...) establishes a non-null caller Principal and/or at least a single AS group Principal and returns AuthStatus.SUCCESS; otherwise you will get a null despite having set the callback property.
This should be possible by checking for the AuthConfigProvider, which can be done via:
First define helper method:
String getAppContextID(ServletContext context)
return context.getVirtualServerName() + " " + context.getContextPath();
}
Then call this code when the ServletContext is available, like in a #WebListener:
AuthConfigFactory factory = AuthConfigFactory.getFactory();
String appContextID = getAppContextID(context);
AuthConfigProvider provider = factory.getConfigProvider("HttpServlet", appContextID, null);
Is there any reason to write
corsFilter.setAllowedOrigins(new HashSet<String>(Arrays.asList("*")));
where the definition of allowedOrigins in the Restlet framework is
private Set<String> allowedOrigins = SetUtils.newHashSet("*");
Another question - when I write the above line, I get an error running my app.
For some reason I get duplicate origin, and the client refuses to accept it - in the request I can see "*" and the domain name where I sent the request from.
How does this duplication can happen, and what is the best way to deal with it?
You're right, there is no need to provide this value as it is already the default one. Could you tell me where you read that such value must be set?
I don't understand what really happens with the second part of your question, as I'm not able to reproduce it (with CorsFilter, or CorsService).
Could you try using the CorsService instead? This service helps to configure the Cors feature, and is integrated in the list of services either of the Application, or the Component, for example in the constructor of the application:
public TestCorsApplication() {
CorsService corsService = new CorsService();
corsService.setAllowedCredentials(true);
corsService.setSkippingResourceForCorsOptions(true);
getServices().add(corsService);
}
I need to be able to update the refreshInterval for JMS client programmatically.
I tried to do it through JmsConfiguration bean, but that's useless, and I couldn't find any configuration on the ActiveMQConnectionFactory class that I could use to update that value.
You can set the recoveryInterval property on the ActiveMQComponent/JmsComponent or set the same property on the JmsConfiguration POJO.
However, since the Camel ActiveMQ/JMS consumer is based on a Spring JMS listeners, like DefaultMessageListenerContainer, you cannot simply change that parameter during runtime (if that's what you intend). You need to set the recoveryInterval before the route is created. You can of course recreate the route and possibly ActiveMQ component and have the recovery interval set programmatically.
If you really need this feature, you can subclass DefaultMessageListenerContainer to allow setRecoveryInterval to actually trigger during runtime (not sure how easy that is, there is some thread handling to watch out for). Your custom MLC can be supplied to camel via the messageListenerContainerFactoryRef option.