I am attempting to abruptly disconnect from an SFTP connection in Java without using the sftp.disconnect() method. Using this to build an integration test that checks that clean up happens everytime. See the test below:
public void checkDisruptedConnections() throws JSchException, InterruptedException {
ChannelSftp sftp = setupSftp(null);
sftp.connect();
try {
//disrupt connection OVER HERE
} catch (Exception e) {
assertEquals("1", jedis.get(SESSION_KEY));
}
waitForConnectionClose();
assertEquals("0", jedis.get(SESSION_KEY));
}
Ended up using a separate thread that connects and gets interupted.
#Test
public void testSftpInterupt() throws InterruptedException, JSchException, SftpException {
Connect thread = new Connect();
thread.start();
while (thread.isAlive()) {
waitForConnectionClose();
}
waitForConnectionClose();
assertEquals("0", jedis.get(SESSION_KEY));
}
Connect looks as follows:
private class Connect extends Thread {
#Override
public void run() {
ChannelSftp sftp = null;
Thread thread = this;
SftpProgressMonitor monitor = new SftpProgressMonitor() {
#Override
public void init(int op, String src, String dest, long max) {
}
#Override
public boolean count(long count) {
currentThread().interrupt();
return false;
}
#Override
public void end() {
}
};
try {
sftp.connect();
sftp.put(LOCAL_FILE_LARGE, remoteFile, monitor);
} catch (JSchException | SftpException e) {
assertEquals("java.io.InterruptedIOException", e.getMessage());
}
}
}
Related
I would like to stop my current transfer file with using method stopUpload() :
private ChannelSftp channelSftp
private ChannelSftp setupJsch() throws JSchException {
JSch jsch = new JSch();
jsch.setKnownHosts("/Users/john/.ssh/known_hosts");
Session jschSession = jsch.getSession(username, remoteHost);
jschSession.setPassword(password);
jschSession.connect();
return (ChannelSftp) jschSession.openChannel("sftp");
}
public void stopUpload()
{
channelSftp.disconnect();
}
public void whenUploadFileUsingJsch_thenSuccess() throws JSchException, SftpException {
ChannelSftp channelSftp = setupJsch();
channelSftp.connect();
String localFile = "src/main/resources/sample.txt";
String remoteDir = "remote_sftp_test/";
channelSftp.put(localFile, remoteDir + "jschFile.txt");
channelSftp.exit();
}
When stopUpload() run I have this error : Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
To cleanly cancel a JSch SFTP transfer, when you need, implement the SftpProgressMonitor interface:
public class CancellableProgressMonitor implements SftpProgressMonitor {
private boolean cancelled;
public CancellableProgressMonitor() {}
public void cancel() {
this.cancelled = true;
}
public bool wasCancelled() {
return this.cancelled;
}
public void init(int op, java.lang.String src, java.lang.String dest, long max) {
this.cancelled = false;
}
public boolean count(long bytes) {
return !this.cancelled;
}
public void end() {
}
}
And pass it to ChannelSftp.put:
CancellableProgressMonitor monitor = new CancellableProgressMonitor()
channelSftp.put(localFile, remoteDir + "jschFile.txt", monitor);
Call monitor.cancel() when you need to cancel the transfer.
public void stopUpload() {
monitor.cancel();
}
If you want to cleanup the partially transferred file:
String remoteFile = remoteDir + "jschFile.txt";
try {
channelSftp.put(localFile, remoteFile, monitor);
} catch (IOException e) {
if (monitor.wasCancelled() && channelSftp.getSession().isConnected()) {
try {
channelSftp.rm(remoteFile);
} catch (SftpException e) {
if (e.id == SSH_FX_NO_SUCH_FILE) {
// can happen if the transfer was cancelled
// before the file was even created
} else {
throw e;
}
}
}
throw e;
}
I wonder why without the code remarked as 1, even the result is not null, the application keeps running and never stop, and the code remarked as 2 doesn't print the expected result.
But with the code remarked as 1, the application finishes when the result is not null,and prints the code which remarked as 2.
AsyncMethodCallback
private Object response=null;
public Object getResponse() {
return response;
}
#Override
public void onComplete(Object response) {
this.response=response;
}
#Override
public void onError(Exception exception) {
exception.printStackTrace();
}
Async Server
public static void main(String[] args) {
try {
TNonblockingServerSocket serverSocket=new TNonblockingServerSocket(10005);
Hello.Processor<Hello.Iface> processor=new Hello.Processor<>(new HelloServiceImpl());
TNonblockingServer.Args serverArgs=new TNonblockingServer.Args(serverSocket);
TProtocolFactory factory=new TBinaryProtocol.Factory();
serverArgs.transportFactory(new TFramedTransport.Factory());
serverArgs.processor(processor);
serverArgs.protocolFactory(factory);
TServer server=new TNonblockingServer(serverArgs);
System.out.println("server start....");
server.serve();
} catch (TTransportException e) {
e.printStackTrace();
}
}
Async Client
public static void main(String[] args) {
try {
TAsyncClientManager clientManager=new TAsyncClientManager();
TNonblockingSocket socket=new TNonblockingSocket("localhost",10005);
TProtocolFactory protocolFactory=new TBinaryProtocol.Factory();
Hello.AsyncClient asyncClient=new Hello.AsyncClient(protocolFactory,clientManager,socket);
System.out.println("Client calls....");
MethodCallback<Integer> methodCallback=new MethodCallback<>();
asyncClient.helloInt(14,methodCallback);
Object result=methodCallback.getResponse();
while (result==null){
result=methodCallback.getResponse();
// System.out.println("result is "+result); //1
}
System.out.println(result); //2
} catch (IOException | TException e) {
e.printStackTrace();
}
}
I need to close connection but I get this
2016-10-28 10:46:07.624:WARN:oeji.nio:handle failed
java.lang.NullPointerException: ssl == null
at com.android.org.conscrypt.NativeCrypto.SSL_read_BIO(Native Method)
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:477)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:1014)
at org.eclipse.jetty.io.nio.SslConnection.unwrap(SslConnection.java:536)
at org.eclipse.jetty.io.nio.SslConnection.process(SslConnection.java:359)
at org.eclipse.jetty.io.nio.SslConnection.access$900(SslConnection.java:48)
at org.eclipse.jetty.io.nio.SslConnection$SslEndPoint.fill(SslConnection.java:678)
at org.eclipse.jetty.websocket.WebSocketParserRFC6455.parseNext(WebSocketParserRFC6455.java:181)
at org.eclipse.jetty.websocket.WebSocketConnectionRFC6455.handle(WebSocketConnectionRFC6455.java:225)
at org.eclipse.jetty.io.nio.SslConnection.handle(SslConnection.java:196)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:833)
This is my code for sockets:
private WebSocket webSocket = new WebSocket.OnTextMessage() {
#Override
public void onMessage(String data) {
//...
}
#Override
public void onOpen(Connection connection) {
//...
}
#Override
public void onClose(int closeCode, String message) {
//...
// this is called after connection.close()
}
};
WebSocketClientFactory webSocketClientFactory = new WebSocketClientFactory();
public void start(){
webSocketClientFactory.stop();
String urlConnect = "wss://test.test.com:111111/websocket";
webSocketClientFactory.setBufferSize(100000);
webSocketClientFactory.start();
WebSocketClient webSocketClient = webSocketClientFactory.newWebSocketClient();
webSocketClient.setMaxBinaryMessageSize(100000);
webSocketClient.setMaxTextMessageSize(100000);
Future<WebSocket.Connection> connectionFuture = webSocketClient.open(URI.create(urlConnect), webSocket);
}
// .......
// after some time call this
public void stop(){
try {
connection.close(); //this is going fine, error comes after
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
I can't understand what is the reason of that error and how I can fix it? I look through jetty docs and checked some thread here, but found nothing about that specific error
You have to stop the WebSocketClient.
Try this:
public void stop(){
try {
webSocketClient.stop();
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
or
public void stop(){
try {
webSocketClient.stop();
connection.close();
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
Link: where I have see it
While it is qute clear how to configure multi-threaded jBehave run,
it is not qute clear for me how to deal with logging mess.
What are the options here?
Rederect application's output to std out (JBehave's one is already there). Notice follow=true
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.follow=true
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-64.64C %4L | %m%n
log4j.rootLogger=error, stdout
log4j.logger.com.company.app.interesting.module=debug
...
Per thread file output
#SuppressWarnings("resource")
public class ThreadFileOutput extends PrintStream {
private static ThreadLocal<FileOutputStream> threadOutput = new ThreadLocal<>();
private static PrintStream stdout = System.out;
private static PrintStream stderr = System.err;
static {
System.setOut(new ThreadFileOutput(stdout));
System.setErr(new ThreadFileOutput(stderr));
}
public ThreadFileOutput(OutputStream out) {
super(out);
}
public static void startThreadOutputRedirect(FileOutputStream stream) {
threadOutput.set(stream);
}
public static void stopThreadOutputRedirect() {
FileOutputStream stream = threadOutput.get();
if (stream != null) {
threadOutput.set(null);
try {
stream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void forceOut(String line) {
stdout.println(line);
}
public static void forceErr(String line) {
stderr.println(line);
}
#Override
public void write(byte[] b) throws IOException {
FileOutputStream stream = threadOutput.get();
if (stream != null) {
try {
stream.write(b);
} catch (IOException e) {
threadOutput.set(null);
throw new RuntimeException(e);
}
} else {
super.write(b);
}
}
#Override
public void write(int b) {
FileOutputStream stream = threadOutput.get();
if (stream != null) {
try {
stream.write(b);
} catch (IOException e) {
threadOutput.set(null);
throw new RuntimeException(e);
}
} else {
super.write(b);
}
}
#Override
public void write(byte[] buf, int off, int len) {
FileOutputStream stream = threadOutput.get();
if (stream != null) {
try {
stream.write(buf, off, len);
} catch (IOException e) {
threadOutput.set(null);
throw new RuntimeException(e);
}
} else {
super.write(buf, off, len);
}
}
#Override
public void flush() {
FileOutputStream stream = threadOutput.get();
if (stream != null) {
try {
stream.flush();
} catch (IOException e) {
threadOutput.set(null);
throw new RuntimeException(e);
}
} else {
super.flush();
}
}
}
Start redirecting thread output to the file befor the test and stop it after the test
startThreadOutputRedirect(new FileOutputStream(new File(workDirRelative(story.getPath()))));
stopThreadOutputRedirect();
in
/**
* JBehave to TC integration.
*/
public class TeamCityReporter extends NullStoryReporter {
private static final LookupTranslator ESCAPE_TABLE = new LookupTranslator(new String[][] {
{ "'", "|'" },
{ "\n", "|n" },
{ "\r", "|r" },
{ "\\u", "|0x" },
{ "|", "||" },
{ "[", "|[" },
{ "]", "|]" }
});
private ThreadLocal<Story> story = new ThreadLocal<>();
private ThreadLocal<String> scenario = new ThreadLocal<>();
#Override
#SuppressWarnings("resource")
public void beforeStory(Story story, boolean givenStory) {
this.story.set(story);
this.scenario.set(null);
try {
startThreadOutputRedirect(new FileOutputStream(new File(workDirRelative(story.getPath()))));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
forceOut(format("##teamcity[testSuiteStarted name='%s']", escape(story.getPath())));
out.println(story.getPath());
super.beforeStory(story, givenStory);
}
#Override
public void afterStory(boolean givenStory) {
forceOut(format("##teamcity[testSuiteFinished name='%s']", escape(story.get().getPath())));
stopThreadOutputRedirect();
super.afterStory(givenStory);
}
#Override
public void beforeScenario(String scenario) {
this.scenario.set(scenario);
forceOut(format("##teamcity[testStarted name='%s']", escape(scenario)));
out.println(scenario);
super.beforeScenario(scenario);
}
#Override
public void afterScenario() {
forceOut(format("##teamcity[testFinished name='%s']", escape(scenario.get())));
this.scenario.set(null);
super.afterScenario();
}
#Override
public void beforeStep(String step) {
out.println(format("\n%s\n", step));
super.beforeStep(step);
}
#Override
public void storyNotAllowed(Story story, String filter) {
forceOut(format("##teamcity[message text='story not allowed %s' status='WARNING']", escape(story.getName())));
out.println(format("\n(Not allowed) %s\n", story.getPath()));
super.storyNotAllowed(story, filter);
}
#Override
public void failed(String step, Throwable cause) {
forceOut(format("##teamcity[testFailed name='%s' message='%s' details='%s']", new String[] { escape(scenario.get()), escape(getRootCauseMessage(cause)), escape(getStackTrace(cause)) }));
out.println(format("\n(Failed) %s\n", step));
cause.printStackTrace();
super.failed(step, cause);
}
#Override
public void pending(String step) {
forceOut(format("##teamcity[testFailed name='%s' message='Step in PENDING state: %s']", escape(scenario.get()), escape(step)));
out.println(format("\n(Pending) %s\n", step));
super.pending(step);
}
#Override
public void notPerformed(String step) {
out.println(format("\n(Not performed) %s\n", step));
super.notPerformed(step);
}
private static String escape(String string) {
return ESCAPE_TABLE.translate(string);
}
}
Turn on parallel JBehave execution
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {
...
})
public class Stories extends JUnitStories {
#Before
public void setUp() throws Exception {
configuredEmbedder()
// turn on parallel test execution
.useExecutorService(newFixedThreadPool(30, new ThreadFactoryBuilder()
.setDaemon(true)
.build()));
configuredEmbedder()
.embedderControls()
...
// don't use it this way not to produce multiThreading = true and delayed StoryReporter callbacks
// and you will see your application logging 'for each jbehave step'
// .useThreads(30);
}
#Override
public Configuration configuration() {
return new MostUsefulConfiguration()
...
.useStoryReporterBuilder(new StoryReporterBuilder()
...
.withFormats(HTML)
.withReporters(teamCityReporter));
}
}
As a result, there will be a log file for each parallel test having both test output and application output (only the code being executed by test runner thread).
Bonus - TeamCityReporter (JBehave to TC integration) will successfully count running parallel tests in real time and report any test failures on TC GUI. Configure test output directory as TC artifact path to access each test output.
Applet freezes when I use Netty 4.0. If I use the Netty 3, the Applet starts correctly. My code is very simple, and I can not understand where the mistake.
public class Applet extends JApplet
{
#Override
public void init()
{
try {
new DiscardServer(1020).run();
} catch (Exception ex) {
Logger.getLogger(Applet.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class DiscardServer {
private final int port;
public DiscardServer(int port) {
this.port = port;
}
public void run() throws Exception {
ServerBootstrap b = new ServerBootstrap();
try {
b.group(new NioEventLoopGroup(), new NioEventLoopGroup()).channel(NioServerSocketChannel.class).localAddress(port)
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
});
ChannelFuture f = b.bind().sync();
f.channel().closeFuture().sync();
} finally {
b.shutdown();
}
}
}
public class DiscardServerHandler extends ChannelInboundByteHandlerAdapter {
private static final Logger logger = Logger.getLogger(DiscardServerHandler.class.getName());
#Override
public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
System.out.println("Message " + new String(in.array()));
in.clear();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.log(Level.WARNING,"Unexpected exception from downstream.",cause);
ctx.close();
}
}
Last post in the console:
network: Cache entry not found [url: file:/D:/java/Applet/dist/lib/netty-4.0.0.Alpha6-20121021.180934-2.jar, version: null]
basic: Plugin2ClassLoader.getPermissions CeilingPolicy allPerms
If I remove the line:
ChannelFuture f = b.bind().sync();
, the applet starts, but the DiscardServer is not working.