2016-07-13 3 views
0

아래 코드에서 try 블록의 첫 번째 행에서 ConnectException이 throw되면 catch되지 않습니다. 원래의 예외 메시지 인 "Connection Refused"는 디버깅에 유용하지 않으므로이 예외를 다시 고려하므로 몇 가지 추가 정보를 추가하려고합니다. 그러나 "연결하지 못했습니다 ..."메시지가 표시되지 않습니다. 나는 원래 "Connection Refused"예외 메시지 만 보았습니다.스칼라의 스칼라 Try/Catch 블록이 예외를 catch하지 못함

private[this] def getClient(system: ActorSystem, config: Config): ConfigException Xor Conn = 
    for { 
    natsConfig <- config.configAt("messaging.nats") 
    userName <- natsConfig.readString("user") 
    password <- natsConfig.readString("password") 
    host  <- natsConfig.readString("host") 
    port  <- natsConfig.readString("port") 
    } yield { 
    val props = new Properties() 
    props.put("servers", "nats://" + userName + ":" + password + "@" + host + ":" + port) 
    log.debug("NATS connection properties:" + props.getProperty("servers")) 
    try { 
     val client = Conn.connect(props) 
     system.registerOnTermination { 
     client.close() 
     } 
     client 
    } catch { 
     case ex:ConnectException => 
     throw new ConnectException("Failed to connect to nats using props:" + props.getProperty("servers")) 
    } 
    } 

내가 얻을 출력은 다음과 같습니다

내가 | 16 : 25 : 15.561 | ogsmessaging.MessageBusManager의 $ |부터 NATS java.net.ConnectException : 연결이 sun.nio에서 을 거부했다. ch.Net.connect0 (기본 방법) at sun.nio.ch.Net.connect (Net.java:454) at sun.nio.ch.Net.connect (Net.java:446) at sun.nio .ch.SocketChannelImpl.connect (SocketChannelImpl.java:648) at java.nio.channels.SocketChannel.open (SocketChannel.java:189) org.nats.Connection.connect (Connection.java:211) at org.nats.Connection. (Connection.java:164) at org.nats.Conn. (Conn.scala : 5) at org. nats.Conn $ .connect (Conn.scala : 68) org.genivi.sota.messaging.nats.NatsClient $$ anonfun $ getClient $ 1 $$ anonfun $ 적용 $ 3 $$ anonfun $ 적용 $ 4 $$ anonfun $ 적용 $ 5 $$ anonfun $ apply $ 6.apply (NatsClient.scala : 30)

catch 블록에있는 예외 메시지와 일치하지 않는 예외 메시지에 유의하십시오. NatsClient : 30은 catch 블록의 첫 번째 줄입니다.

위의 코드는 scala_nats를 사용하여 NATS 메시징 서버에 연결하려고합니다. 캐치 케이스를 Throwable로 변경해도 예외는 여전히 잡히지 않습니다. 그러나 try의 첫 번째 줄에 ConnectException을 throw하면 해당 예외가 catch됩니다. 나는 또한 루트을 내 수입에 추가하여 아무런 문제없이 네임 스페이스 충돌이 없는지 확인했습니다.

여기서 스칼라가 예외를 잡는 데 실패 할 수있는 상황은 무엇입니까?

+2

어떻게 잡히지 않았다고 판단합니까? – Dima

+0

원본 ConnectException에 "Connection Refused"메시지가 있습니다. 던진 예외에는 다른 문자열이 있지만 로그에서 "Connection Refused"만 볼 수 있습니다. – CalumMcCall

+0

아마도 잡기 전에 기록 될 것입니까? – Dima

답변

2

Java_Nats 라이브러리에 Connection.java의 관련 코드 :

private boolean connect() throws IOException { 
    try { 
     InetSocketAddress addr = new InetSocketAddress(servers[current].host, servers[current].port); 
     channel = SocketChannel.open(addr); 
     while(!channel.isConnected()){}   
     servers[current].connected = true; 
    } catch(Exception ie) { 
     ie.printStackTrace(); 
     return false; 
    } 

    return true; 
} 

하여 스택 트레이스에 따르면, SocketChannel.open()이 실패합니다. 그런 다음 예외가 잡히고, 기록되고 삼켜 져서 처리기에 도달하지 않습니다.

N.b. 위의 코드는 라이브러리 버전 0.5.1에서 가져온 것입니다. 최신 (0.6.0)의 것이 갱신되어 IOException를 슬로우 해, 로깅은 슬로우하지 않습니다.


는 (내 원래의 대답은 예외가 잡힌하지만 즉시 다른 하나를 던져 완전히 떨어져 :

했다. 제 생각에는 대신 예외 객체를 Xor.left 으로 반환 (던지지 않음)하려고합니다. (적어도 이것은 선언 된 반환 유형 ConfigException Xor Conn가 제안하는 것입니다.)

+0

나는 명확하지 않았다. 디버깅을 돕기 위해 더 많은 정보가 추가되어 예외가 다시 발생합니다. 문제는 catch 블록이 절대로 실행되지 않는다는 것입니다. – CalumMcCall

+0

저는 실제로 0.5.1을 사용하고 있습니다. 훌륭한 질문에 대해 감사 드리며 특히 명확하지 않은 질문이 있습니다. – CalumMcCall

2

ConnectException 는이 라인에 포착되고있다 :

} catch { 
    case ex:ConnectException => println("HELLO!!!") 

하지만 당신은 즉시 다른 ConnectException을 던지고있다.

일반적으로 다른 예외로 예외를 래핑해서는 안됩니다.

여기서 볼 수 있듯이 try 블록을 전혀 사용하지 마십시오!

+0

예,이 경우에는 예외를 재실행하기 전에 예외에 더 많은 정보를 추가하려고합니다. 그러나 예외는 결코 다시는 용납되지 않는다. – CalumMcCall

+0

정확하게 말하자면, 더 나은 정보로 * 새로운 * 예외 인스턴스를 생성하고 있습니다. 잡힌 것을 던지면 안됩니다. – Det

+0

네, 맞습니다. 미안, 나는 거기에서 분명하지 않았다. – CalumMcCall

관련 문제