Spring Integration CachingSessionFactory: What does setTestSession(true) do? - spring

I'm working with the CachingSessionFactory and I was wondering what the property `setTestSession(boolean testSession) does and when to use it?
The docs are not telling a lot about what it does: https://docs.spring.io/spring-integration/api/org/springframework/integration/file/remote/session/CachingSessionFactory.html#setTestSession(boolean)

See SFTP docs: https://docs.spring.io/spring-integration/docs/current/reference/html/sftp.html#sftp-session-caching
Starting with version 5.1, the CachingSessionFactory has a new property testSession. When true, the session will be tested by performing a REALPATH command for an empty path to ensure it is still active; if not, it will be removed from the cache; a new session is created if no active sessions are in the cache.
The logic there in the cache is like this:
public boolean isStale(Session<F> session) {
return CachingSessionFactory.this.testSession ? !session.test() : !session.isOpen();
}
See SftpSession for implementation details.

Related

Aws integration spring: Extend Visibility Timeout

Is it possible to extend the visibility time out of a message that is in flight.
See:
http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html.
Section: Changing a Message's Visibility Timeout.
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sqs/AmazonSQSClient.html#changeMessageVisibility-com.amazonaws.services.sqs.model.ChangeMessageVisibilityRequest-
In summary I want to be able to extend the first set visibility timeout for a given message that is in flight.
Example if 15secs have passed I then want to extend the timeout by another 20secs. Better example in java docs above.
From my understanding in the links above you can do this on the amazon side.
Below are my current settings;
SqsMessageDrivenChannelAdapter adapter =
new SqsMessageDrivenChannelAdapter(queue);
adapter.setMessageDeletionPolicy(SqsMessageDeletionPolicy.ON_SUCCESS);
adapter.setMaxNumberOfMessages(1);
adapter.setSendTimeout(2000);
adapter.setVisibilityTimeout(200);
adapter.setWaitTimeOut(20);
Is it possible to extend this timeout?
Spring Cloud AWS supports this starting with Version 2.0. Injecting a Visiblity parameter in your SQS listener method does the trick:
#SqsListener(value = "my-sqs-queue")
void onMessageReceived(#Payload String payload, Visibility visibility) {
...
var extension = visibility.extend(20);
...
}
Note, that extend will work asynchronously and will return a Future. So if you want to be sure further down the processing, that the visibility of the message is really extended at the AWS side of things, either block on the Future using extension.get() or query the Future with extension.isDone()
OK. Looks like I see your point.
We can change visibility for particular message using API:
AmazonSQS.changeMessageVisibility(String queueUrl, String receiptHandle, Integer visibilityTimeout)
For this purpose in downstream flow you have to get access to (inject) AmazonSQS bean and extract special headers from the Message:
#Autowired
AmazonSQS amazonSqs;
#Autowired
ResourceIdResolver resourceIdResolver;
...
MessageHeaders headers = message.getHeaders();
DestinationResolver destinationResolver = new DynamicQueueUrlDestinationResolver(this.amazonSqs, this.resourceIdResolver);
String queueUrl = destinationResolver.resolveDestination(headers.get(AwsHeaders.QUEUE));
String receiptHandle = headers.get(AwsHeaders.RECEIPT_HANDLE);
amazonSqs.changeMessageVisibility(queueUrl, receiptHandle, YOUR_DESIRED_VISIBILITY_TIMEOUT);
But eh, I agree that we should provide something on the matter as out-of-the-box feature. That may be even something similar to QueueMessageAcknowledgment as a new header. Or even just one more changeMessageVisibility method to this one.
Please, raise a GH issue for Spring Cloud AWS project on the matter with link to this SO topic.

Has the StackExchange Redis connection config changed?

I have been using the following to connect to Redis without issue until today, now I have to explicitly state provide a database parameter because of this:
ArgumentOutOfRangeException
Specified argument was out of the range of valid values. Parameter name: db at StackExchange.Redis.ConnectionMultiplexer.GetDatabase(Int32 db, Object asyncState) at MyServer.MyClass..cctor()
This is the config I have been using:
private static Lazy<ConnectionMultiplexer> MyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect(MyRedisConnString);
});
public static ConnectionMultiplexer ConnGer
{
get
{
return MyConnection.Value;
}
}
and at class level:
private static readonly IDatabase RedisDb = RedisConfig.ConnGer.GetDatabase();
Providing the db parameter thus:
RedisConfig.ConnGer.GetDatabase(0);
fixed the error of course; more of a concern is whether there have been any seeming breaking changes recently as my class libraries are littered with Redis!
UPDATE
After thinking I had resolved the issue, for no apparent reason the ConnectionMultiplexer started failing again with the above config. I tried defaultDatabase=0 in the string and also tried as a Configuration.Option and got this error:
Exception type: ArgumentException
Exception message: Keyword 'defaultDatabase' is not supported
at StackExchange.Redis.ConfigurationOptions.OptionKeys.Unknown(String key)
at StackExchange.Redis.ConfigurationOptions.DoParse(String configuration, Boolean ignoreUnknown)
at StackExchange.Redis.ConnectionMultiplexer.CreateMultiplexer(Object configuration)
at StackExchange.Redis.ConnectionMultiplexer.ConnectImpl(Func 1 multiplexerFactory, TextWriter log)
at System.Lazy1.CreateValue()`
and with the ConfigOption mode:
Exception type: TypeInitializationException
Method not found: 'Void StackExchange.Redis.ConfigurationOptions.set_DefaultDatabase(System.Nullable 1<Int32>)'.
I also removed the System.Lazy part of the config too, same errors.
Putting the 0 value in as a GetDatabase() parameter stopped the error for now; the concern remains that this doesn't match the documented implementation.
You are probably specifying a wrong default database in the config?
Try adding defaultDatabase=0 to your connection string.
See the configuration options.
This is a bit of an old one, but I just experienced it out of the nowhere. The server rebooted from a windows update and then the errors began occurring whilst they'd been running fine for a very long time.
To fix it, I just updated to the latest version of the dll.

How to temporarily disable protocol tracing during a JavaMail IMAP connection

You can specify whether JavaMail emits a protocol-level trace either when setting the Properties for your Session (by setting the "mail.debug" property to "true") or by calling Session.setDebug before you do the store connect.
However, when the Protocol object gets instantiated, it creates a "protocol" TraceLogger that persists for the lifetime of the protocol object. Which appears to mean that you can't temporarily disable protocol-level debug logging on a connection once you start using it.
There is a Protocol.suspendTracing method. And it does allow you to temporarily turn off protocol trace output. A bunch of the IMAP auth methods use it to keep your credentials out of the logfile. But suspendTracing is protected, so it's not callable from regular user code.
Is there another way to temporarily turn off IMAP protocol tracing? (I'd prefer temporarily turning off just the traceInput logging, but I'm fine with disabling all logging.) Do I need to write and register a whole Protocol subclass so I can get access to Protocol.suspendTracing?
You could use Session.setDebugOut to set your own stream and control it from there.
If you're using java.util.logging, you can change the logging level at any time.
Not the best solution but, you can install a custom log filter on the com.sun.mail.imap.protocol logger to check that some specific thread is allowed to produce output. Assuming your connection is local to one thread
public class ServiceFilter implements Filter {
private static final ThreadLocal<javax.mail.Service> id = new ThreadLocal<>();
public static void suspendTracing(javax.mail.Service s) {
id.set(Objects.requireNonNull(s));
}
public static void enableTracing(javax.mail.Service s) {
if (s.equals(id.get())) {
id.remove();
}
}
#Override
public boolean isLoggable(LogRecord record) {
return id.get() == null;
}
}
The downside is that this code becomes part of your project and it is another resource that you have to manage.

Grails Spring Security Static Rules

I want all users to be authenticated before accessing my application. Following is the setting in Config.groovy:
grails.plugin.springsecurity.controllerAnnotations.staticRules=[
"/**": ["ROLE_ADMIN"],
"/login/auth": ["permitAll"]
]
The reason I put "/login/auth": ["permitAll"] is that any user can have a chance to log in and be authenticated. However, when I access http://localhost:8080/myapp/, it redirects to http://localhost:8080/myapp/login/auth and throws the error: The page isn't redirecting properly. Can you please advise what mistake I have committed here?
For first you must say to spring security what type of mapping you will be use.
grails.plugins.springsecurity.securityConfigType = 'InterceptUrlMap'
For second 'permitAll' changed to 'IS_AUTHENTICATED_ANONYMOUSLY'
And for third, if spring security find /** he didn't see another under this line. So your code must be like this:
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = [
"/login/auth": ["permitAll"],
"/**": ["ROLE_ADMIN"]
]
TrongBang and Koloritnij are on the right track. But they're not completely correct in the context of your question. They're suggesting that you switch to a different authentication setup. (Which that will work but it doesn't solve the problem in the context of your setup.)
If you wish to keep the annotations, you're going to have to call out the controller that OAuth uses.
‘/springSecurityOAuth/**’: [‘permitAll’]
The plugin maps that controller path, but the static rules still interprets the controller and methods from that.
This took some digging for me to find this out. I had your same issue, and I blogged about this (and it includes some of the details about how the Spring Security Oauth plugin works.
http://theexceptioncatcher.com/blog/2015/04/spring-security-oauth-the-missing-instructions/
The solution from Koloritnij is correct. However, it threw the following error when using SecurityConfigType.InterceptUrlMap:
ERROR: the 'securityConfigType' property must be one of
'Annotation', 'Requestmap', or 'InterceptUrlMap' or left unspecified
to default to 'Annotation'; setting value to 'Annotation'
I have changed it to 'InterceptUrlMap' only and it worked:
grails.plugins.springsecurity.securityConfigType = 'InterceptUrlMap'
grails.plugins.springsecurity.interceptUrlMap = [
"/login/auth": ["permitAll"],
"/**": ["ROLE_ADMIN"]
]

How does someone use Guava's CacheLoader asynchronously

The question says it all I'd like to use CacheBuilder, but my values are pulled in asynchronously. This worked previously with MapMaker as the CacheLoader wasn't a requirement. Now I'd like to know if I can hack this up or if there are any non deprecated alternatives. Thank you.
I think the question you're trying to ask is "How can I use CacheBuilder without having to specify a CacheLoader?" If that's the case, then there will be support for this in Guava release 11.0. In the meantime a build() method on CacheLoader is already checked into trunk (as of this morning):
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/cache/CacheBuilder.html
One method would be to make with generic parameters K and V as your desired outputs:
LoadingCache<K, ListenableFuture<V>> values = CacheBuilder.newBuilder()
.build(
new CacheLoader<K, ListenableFuture<V>>() {
public ListenableFuture<V> load(K key) {
/* Get your future */
}
});

Resources