2016-09-11 4 views
0

싱글 사인온을 사용하는 로그인을 만들고 있습니다. 이렇게하려면 사용자가 로그인하는 회사가 SSO를 사용하는 경우 JavaFX WebView이 열리고 사용자가 로그인 할 수 있습니다. 이 로그인은 완전히 웹 기반이므로 내 데이터를 캡처 할 필요가 없습니다.JavaFX 응용 프로그램에서 showAndWait 사용

두 클래스가 LoginManagerSSO입니다. LoginManager은 회사가 SSOEnabled인지 확인한 다음 SSO으로 이동합니다. 여기에서 UI를 만든 다음 Platform.runLater()을 사용하여 webview이라는 메서드로 이동합니다. 그러나 내 프로그램은 initJFXPanel으로 이동 한 다음 즉시 코드를 실행하기 위해 LoginManager으로 돌아가므로 문제가됩니다.

내가 원하는 것은 특정 웹 페이지에 도달 할 때까지 SSO을 모두 통과 한 다음 frame.dispose()를 사용하고 다시 LoginManager으로 이동하여 계속 진행하는 것입니다. 나는 StageshowAndWait()을 사용할 필요가 있다고 생각하지만, 이것에 대해 어떻게 해야할지 잘 모르겠습니다.

나는 initJFXPanel 내부의 무대를 만드는 시도했지만 아무것도 할 수있는 기회를 가지고 전에이는 LoginManager로 돌아갑니다 작동하지 않았고, 나 또한 createPopup의 단계를 설정하려하지만 난 사용하는 것을 확실하지 않았다 무대 나 장면으로.

LoginManager 클래스 어떤 도움에 감사드립니다

public class SSO { 

    private JFrame frame; 
    private JFXPanel fxPanel; 
    private JPanel containerPanel; 
    final static String WEBVIEW = "WebView"; 

    public SSO(){ 
     createPopup(); 
    } 

    private void createPopup(){ 

     Dimension size = new Dimension(480, 80); 

     frame = new JFrame("Web Login"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     containerPanel = new JPanel(new CardLayout()); 

     fxPanel = new JFXPanel(); 
     fxPanel.setSize(size); 

     Platform.runLater(() -> initJFXPanel(frame, fxPanel)); 

     containerPanel.add(fxPanel, WEBVIEW); 

     frame.add(containerPanel, BorderLayout.CENTER); 

     frame.setPreferredSize(size); 
     frame.setResizable(false); 
     frame.getRootPane().setWindowDecorationStyle(JRootPane.NONE); 

     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

    } 

    private void initJFXPanel(final JFrame frame, final JFXPanel fxPanel){ 

     Group group = new Group(); 
     Scene scene = new Scene(group); 
     fxPanel.setScene(scene); 

     WebView webview = new WebView(); 

     group.getChildren().add(webview); 
     webview.setMinSize(500, 640); 
     webview.setMaxSize(500, 640); 

     CookieManager cookieManager = new CookieManager(); 
     java.net.CookieHandler.setDefault(cookieManager); 

     webview.getEngine().load("http://google.com/"); 


     if(webview.getEngine().getLocation().equalsIgnoreCase("cookie url")) { 
      // harvest the cookies 
     } 
     else if(webview.getEngine().getLocation().equalsIgnoreCase("end url")) { 
      frame.dispose(); 
     } 

    } 

} 

public class LoginManager { 

    private boolean bSSOEnabled = true; 

    private void Login() { 

     // get company details 

     if(bSSOEnabled) { 
      new SSO(); 
     } 

     // once SSO is done, continue with execution 
    } 
} 

SSO 클래스 :

여기 내 코드입니다. 나는 하루 종일 붙어 있었고 무엇을해야할지 잘 모릅니다. 응용 프로그램이 스윙 응용 프로그램입니다, 당신은 WebView를 사용해야하는 경우

+0

1. 스윙과 자바 FX를 혼합해야합니까? 하나의 툴킷 만 사용할 수 있다면 더 쉬울 것입니다. 같은 애플리케이션에서'JFrame'과'Stage'를 모두 사용하고 싶지 않으므로 Swing을 사용하기로 결정했다면'WebView'를'JFXPanel'에 삽입하고'JFrame'에 표시하는 것은 올바른 접근법. 2.'LoginManager'에서'login()'메소드가 호출 된 스레드는 무엇입니까? –

+0

@James_D 1. 아니요. 특별히 아무것도 사용할 필요가 없습니다. UI를 쓰지 않았고, 다른 누군가가 프로젝트를 포기하고 난 다음에 그 프로젝트를 포기 했으므로 변경하지 않아도됩니다. 그게 최선의 방법이라면 showAndWait을 구현하는 데 필요한 것입니다. 2. 나는 그것이 주된 것이라고 생각합니까? – Rachael

+0

나머지 UI는 이미 Swing 또는 JavaFX로 작성되어 있습니까? –

답변

0

는 다음 올바른 접근 방식은 당신이 당신의 코드와 같이 한 사람, 스윙 창을 사용하고 JFXPanelWebView을 포함 즉이다. 일반적으로 두 프레임 워크의 창을 혼합하는 것은 좋지 않으므로 Stage을 전혀 사용하지 않는 것이 좋습니다.

사용자가 JavaFX Stage.showAndWait() 호출의 Swing에 해당하는 것과 같은 창을 닫을 때까지 Swing 블록에서 코드를 작성하는 방법은 JDialog을 사용하고 모달로 만드는 것입니다. 다른 윈도우에 대한 입력을 차단할뿐만 아니라 대화 상자가 없어 질 때까지 (AWT Event Dispatch 스레드의) 실행을 차단합니다.

좀 더 까다로운 이유는 AWT 이벤트 발송 스레드, JavaFX 응용 프로그램 스레드 및 기본 스레드와 같이 세 가지 스레드가 작동해야한다는 것입니다. 모달 대화 상자를 표시하면 AWT Event Dispatch 스레드가 차단되지만 주 스레드가 차단되도록 (질문을 올바르게 이해할 경우) 원합니다. 또한 AWT Event Dispatch 스레드에서만 Swing 구성 요소를 생성, 수정 및 표시해야하며 JavaFX 응용 프로그램 스레드에서 JavaFX 노드를 작성, 수정 및 표시해야합니다. 당신이 SSO를 인스턴스화하는 경우 대화 상자를 해제 할 때까지 이제, 코드를 차단합니다

public class SSO { 

    private JDialog dialog; 
    private JFXPanel fxPanel; 
    private JPanel containerPanel; 
    final static String WEBVIEW = "WebView"; 

    public SSO(){ 
     // creates Swing components: MUST be called on AWT Event thread 
     createPopup(); 
    } 

    private void createPopup(){ 

     Dimension size = new Dimension(480, 80); 

     dialog = new JDialog(); 
     dialog.setTite("Web Login"); 

     // make dialog modal: 
     dialog.setModalityType(ModalityType.APPLICATION_MODAL); 

     // oops: don't want this: 
     // dialog.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     // but this: 
     dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 

     containerPanel = new JPanel(new CardLayout()); 

     fxPanel = new JFXPanel(); 
     fxPanel.setSize(size); 

     Platform.runLater(() -> initJFXPanel(dialog, fxPanel)); 

     containerPanel.add(fxPanel, WEBVIEW); 

     dialog.add(containerPanel, BorderLayout.CENTER); 

     dialog.setPreferredSize(size); 
     dialog.setResizable(false); 
     dialog.getRootPane().setWindowDecorationStyle(JRootPane.NONE); 

     dialog.pack(); 
     dialog.setLocationRelativeTo(null); 
     dialog.setVisible(true); 

    } 

    private void initJFXPanel(final JDialog dialog, final JFXPanel fxPanel){ 

     Group group = new Group(); 
     Scene scene = new Scene(group); 
     fxPanel.setScene(scene); 

     WebView webview = new WebView(); 

     group.getChildren().add(webview); 
     webview.setMinSize(500, 640); 
     webview.setMaxSize(500, 640); 

     CookieManager cookieManager = new CookieManager(); 
     java.net.CookieHandler.setDefault(cookieManager); 

     webview.getEngine().load("http://google.com/"); 


     if(webview.getEngine().getLocation().equalsIgnoreCase("cookie url")) { 
      // harvest the cookies 
     } 
     else if(webview.getEngine().getLocation().equalsIgnoreCase("end url")) { 
      // this will hide the dialog and release the event dispatch thread 
      // that is waiting for it, but it must be called on the event dispatch thread 
      // not sure of your exact requirements, but you may need to do this 
      // in the if clause as well? 
      SwingUtilities.invokeLater(() -> dialog.setVisible(false)); 
     } 

    } 

} 

:

그래서 난 당신이 뭔가를하려는 생각합니다. 그러나 AWT Event Dispatch 스레드에서이를 수행해야합니다.주 스레드에서 완료 할 때까지 기다리는 트릭은 new SSO()FutureTask으로 표시하고 FutureTaskSwingUtilities.invokeLater()에 제출 한 다음 주 스레드로 돌아가 FutureTaskget()으로 전화하면 작업이 완료 될 때까지 차단됩니다 완료됩니다. 여기서주의 할 필요가 있습니다. 실수로 이벤트 발송 스레드에서이 작업을 수행하면 교착 상태가 발생합니다. 이벤트 발송 스레드가 차단되어 이벤트 발송 스레드에서 발생하는 이벤트를 기다리고 있습니다. 안전을 지켜라.

그래서 코드는 아마 다음과 같이해야합니다 :

public class LoginManager { 

    private boolean bSSOEnabled = true; 

    private void Login() { 

     // get company details 

     if(bSSOEnabled) { 
      if (SwingUtilities.isEventDispatchThread()) { 
       // already on EDT, just invoke the SSO which will block 
       // until the dialog is dismissed: 
       new SSO(); 
      } else { 
       // create FutureTask to show dialog, etc: 
       FutureTask<Void> ssoTask = new FutureTask<>(SSO:new, null); 
       // submit task to AWT event dispatch thread: 
       SwingUtilities.invokeLater(ssoTask); 
       // wait for task to complete, i.e. for dialog to be dismissed: 
       try { 
        ssoTask.get(); 
       } catch (InterruptedException exc) { 
        // thread was interrupted, representing cancelation of some kind: 
        System.out.println("Thread interrupted"); 
        Thread.currentThread().interrupt(); 
       } catch (ExecutionException ee) { 
        // something went wrong... 
        throw new RuntimeException(ee); 
       } 
      } 
     } 



    // once SSO is done, continue with execution 
    } 
} 
+0

정말 대단합니다. 정말 고마워요! 대화 상자의 프레임 교환은 LoginManager의 코드 스레딩없이 작동하는 것 같습니다. 이것이 내 프로그램에 부정적인 영향을 줄까요? – Rachael

관련 문제