sialcasa / mvvmFX

an Application Framework for implementing the MVVM Pattern with JavaFX
Apache License 2.0
489 stars 104 forks source link

mvvmFX in combination with shiro -> SecurityUtils.getSubject() breaks viewmodel injection #505

Closed mitvitaminen closed 7 years ago

mitvitaminen commented 7 years ago

Hi, I am having trouble with apache shiro the security framework. When I do a shiro org.apache.shiro.SecurityUtils.getSubject(); to receive a org.apache.shiro.subject.Subject the ViewModel cannot be Injected into the view. I get a bunch of not useful Exceptions, I think it has to do with way the viewmodel is injected. pls fix or point me to a different security framework that is working with mvvmfx because i really like mvvmfx and want to use it. Or do you guys use a different security framework that is working? I am using google guice for injection. Tell me if you need further information. regards Chris Below is the Exception:

Caused by: java.lang.IllegalStateException: Can't inject ViewModel of type <class net.cuscus.client.ui.loginscreen.Login ScreenViewModel> into the view <net.cuscus.client.ui.loginscreen.LoginScreenView@3d4788e8> at de.saxsys.mvvmfx.internal.viewloader.ReflectionUtils.lambda$accessField$3(ReflectionUtils.java:172) at java.security.AccessController.doPrivileged(Native Method) at de.saxsys.mvvmfx.internal.viewloader.ReflectionUtils.accessField(ReflectionUtils.java:166) at de.saxsys.mvvmfx.internal.viewloader.ViewLoaderReflectionUtils.createAndInjectViewModel(ViewLoaderReflectionUtils.ja va:261) at de.saxsys.mvvmfx.internal.viewloader.FxmlViewLoader.handleInjection(FxmlViewLoader.java:292) at de.saxsys.mvvmfx.internal.viewloader.FxmlViewLoader.access$000(FxmlViewLoader.java:44) at de.saxsys.mvvmfx.internal.viewloader.FxmlViewLoader$DefaultControllerFactory.call(FxmlViewLoader.java:274) at de.saxsys.mvvmfx.internal.viewloader.FxmlViewLoader$DefaultControllerFactory.call(FxmlViewLoader.java:256) at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:929) at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971) at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220) at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744) at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707) at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527) ... 16 more

manuel-mauky commented 7 years ago

Hi Chris, in my projects I haven't used Shiro or any other security framework together with mvvmFX. There simply wasn't the requirement for it.

From the exception alone I can't tell what the problem is. Can you post some code of your ViewModel and View class? Interesting is how you inject the ViewModel into the View and how you use the shiro method.

mitvitaminen commented 7 years ago

There is not really much to it :/ The ViewModel is:

`public class LoginScreenViewModel implements ViewModel { private final SimpleStringProperty loginName = new SimpleStringProperty(); private final SimpleStringProperty password = new SimpleStringProperty();

private final Subject   currentUser = SecurityUtils.getSubject();
private DelegateCommand loginCommand;

public SimpleStringProperty getLoginNameProperty() {
    return loginName;
}
public SimpleStringProperty getPasswordProperty() {
    return password;
}
public void initialize() {
    // currentUser = SecurityUtils.getSubject();
    loginCommand = new DelegateCommand(() -> new Action() {
        @Override
        protected void action() throws Exception {
            final UsernamePasswordToken token = new UsernamePasswordToken(loginName.get(), password.get());
            token.setRememberMe(true);
            currentUser.login(token);
            if (currentUser.isAuthenticated()) {
                publish(NotificationMessages.LOGIN_SUCCESS);
            }
        }
    });
}
Command getLoginCommand() {
    return loginCommand;
}

}`

And the View is:

`public class LoginScreenView implements FxmlView { private final Stage primaryStage;

@FXML
private TextField       loginnameTF;
@FXML
private PasswordField   passwordField;
@FXML
private Button          loginButton;

@InjectContext
private Context                 context;
@InjectViewModel
private LoginScreenViewModel    viewModel;

private Command                 loginCommand;
private NotificationObserver    loginObserver;

@Inject
LoginScreenView(Stage primaryStage) {
    this.primaryStage = primaryStage;
}

public void initialize() {
    loginCommand = viewModel.getLoginCommand();
    loginObserver = (key, payload) -> loadMainGuiView();
    viewModel.getLoginNameProperty().bind(loginnameTF.textProperty());
    viewModel.getPasswordProperty().bind(passwordField.textProperty());
    // loginButton.disableProperty().bind(loginCommand.notExecutableProperty());
    viewModel.subscribe(NotificationMessages.LOGIN_SUCCESS, new WeakNotificationObserver(loginObserver));
}
private void loadMainGuiView() {
    final ViewTuple<MainGuiView, MainGuiViewModel> loader = FluentViewLoader.fxmlView(MainGuiView.class).context(context)
                .load();

    final Scene s = new Scene(loader.getView());
    s.getStylesheets().addAll(CusCusClient.cssheet);

    primaryStage.initModality(Modality.APPLICATION_MODAL);
    primaryStage.setScene(s);
    primaryStage.sizeToScene();
    primaryStage.show();
}
@FXML
private void loginAction() {
    loginCommand.execute();
}

}`

If you need the shiro setup let me know, but that is actually initializing just fine.

mitvitaminen commented 7 years ago

wait up I think I found my error this might be redundant thread because of my failure. Be back in a while. XD

mitvitaminen commented 7 years ago

This can be deleted it was something different and thus the ViewModel could not be injected.

manuel-mauky commented 7 years ago

Ok. good to hear.