I am having some troubles with splitting the business logic from a single controller into different controllers.
Problem:
At the beginning of my application,i ask user for username and password to perform login.After that,and if the login succeeds,i want to show to the user the main scene which includes some basic operation my app can do.The problem is : to perform any basic operation(for example,find groups the user belongs to) i need to know the username the user used when he logged in.At first, i made a single controller and passed to it the username from the login scene.Here is the login method from the login controller:
private void login(){
boolean loginResult = false;
try {
//Returns True if the user can login with the given username and password
loginResult = userRemote.login(username_field.getText(), password_field.getText());
if (!loginResult) {
Alert alert = new Alert(Alert.AlertType.ERROR, "The username and/or password are incorrect");
alert.showAndWait();
} else {
loadMain();
}
} catch (RemoteException e) {
e.printStackTrace();
Alert alert = new Alert(Alert.AlertType.ERROR, "Unable to connect to the server.Please try again later");
alert.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
If the login succeeds,i load the main scene passing it the username.Here is the code:
FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/fxml/main.fxml"));
Parent root = loader.load();
Controller controller = loader.getController();
controller.init(username_field.getText());
Stage stage = (Stage) ( (Node) (sign_in_btn) ).getScene().getWindow();
Scene scene = new Scene(root);
scene.getStylesheets().add("/gui/view/css/style.css");
stage.setScene(scene);
In the Controller i save the username in a field,here is the init method that is called :
void init(String username) throws IOException {
this.username = username;
//some other code
}
After that i have the username in the my Controller of the main Scene,but the problem is that because of so many operation the controller has to do,the code in that controller is huge(about 800 lines of code).
I want to ask if there is any way to pass the username to other controllers from a single controller?
The operations my application performs are : finds tasks of the user,finds groups of the user,creates tasks,creates groups,deletes tasks,delete groups.
I use a group of toggle buttons that make the nav bar :
So whenever the user clicks any of the toggle buttons,an appropriate operation is performed using the username he gave when he logged in.
I want each toggle button to load a single fxml view,and each of the views to have its own controller that does the appropriate action using the username.But i don't know how to save the username and pass it to those controllers.
Right know i use a single controller that doesn't use any fxml files,it just creates the appropriate gui,depending on the toggle button that was clicked,and performs the business logic.
Related
I need to handle user's cancel in custom Keycloak SPI Authenticator.
I implemented it and it works fine. All I need is to cancel login flow and start from the begging when user hit cancel
#Override
public void action(AuthenticationFlowContext context) {
logger.debug("action called ... context = " + context);
String cancel = context.getHttpRequest().getDecodedFormParameters().getFirst("cancel");
if (cancel != null) {
context.cancelLogin();
context.resetFlow();
return;
}
// OK handling...
}
In my case I'm getting login page but with wrong URL:
http://localhost:8080/auth/realms/realm1/login-actions/authenticate?execution=bb1fb7c3-0b59-4a07-b997-b619c6f9ea2a&client_id=realm1-client&tab_id=YJxYk7osJaU
instead of URL like this when I enter secured page first time:
http://localhost:8080/auth/realms/realm1/protocol/openid-connect/auth?response_type=code&client_id=realm1-client&redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fsso%2Flogin&state=2cc038b9-2c69-4648-ac39-e5864bc05ee9&login=true&scope=openid
Ah all I need is to left only row (or put it the last before return):
context.cancelLogin();
On my custom application I need to handle endpoint with parameters where KK will redirect me
/sso/login?error=access_denied&state=923e5b18-1d8e-4c96-9fed-c1dd122065bb
In an android app, which uses Parse, the login flow is like this...
We have our own logic to see if the user has entered the correct credentials. Once we verify that, signUpOrLoginOnParse() is called. Parse is used just to store data and handle sessions locally. Users can not access the api without the token.
private void signUpOrLogin(final String username, final String token) {
ParseUser user = new ParseUser();
user.setUsername(username);
user.setPassword(username);
user.signUpInBackground(new SignUpCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
// sign up success. ParseUser.getCurrentUser() populated
saveTokenToCloud(token);
} else if ("condition to check if the user already exists") {
// existing user, login.
ParseUser.logInInBackground(username, username, new LogInCallback() {
#Override
public void done(ParseUser parseUser, ParseException e) {
// login was successful, ParseUser.getCurrentUser() populated
saveTokenToCloud(token);
}
});
} else {
showProgress(false);
e.printStackTrace();
}
}
});
}
private void saveTokenToCloud(String token) {
// saving token to cloud
ParseUser user = ParseUser.getCurrentUser();
user.put("token", token); // THIS IS WHERE I GET NULL POINTER EXCEPTION
user.saveEventually();
// link installation to user.
ParseInstallation parseInstallation = ParseInstallation.getCurrentInstallation();
parseInstallation.put("user", user);
parseInstallation.saveEventually();
// Starting next activity
Intent i = new Intent(this, NextActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
All good when I first run the app. Once, logout button is pressed (contains - Parse.logoutInBackground()), it shows the LoginActivity (current one). When trying to log in, everything succeeds but I get a NullPointerException at line 3 of saveTokenToCloud().
It says - trying to invoke virtual method .put() over a null object reference.
But, isn't Parse.currentUser() already populated since this method is called from callback of methods that do that ?
It works after restarting the app. But then the same continues if logout is pressed.
After calling logoutInBackground , future calls to getCurrentUser() will return null.
You will need to initialize the user again.
signUpInBackground will create a new ParseUser on the server, and also persist the session on disk so that you can access the user using ParseUser.getCurrentUser().
However i am not sure you should be calling it every single time you log in.
Instead of calling the getCurrentuser inside the saveToken method you can pass the user to the saveTokenMethod from the done callback parameter.
Separate you logic in distinct methods for sign up and logIn. I suggest you check before calling signUp, and not abusing it every time you want to login
(note, what i newbie in java)
I a little bit stuck in solving the problem of pass object between javafx scenes and classes.
For example, i have class, which waits for data by server; main class and 2 javafx windows.
Let it looks like this:
Listener.java.
Let it work at another thread. When we got "nelo" from server, then it'll means, what user not logged it, and then, we should open Login Window
// some package
// some imports
public class Listener extends Thread {
public void run() {
System.out.println("[INF] Wait for server...");
while(true) {
handle();
}
}
public void handle()
{
try {
byte[] token = new byte[6];
DataInputStream src = new DataInputStream(in);
src.read(token);
String token_val = new String(token);
switch (token_val) {
case "_nelo_":
System.out.println("[INF] Auth required");
break;
}
} catch (IOException e) {
}
}
}
Okay, there nothing weird. Just simple class for listening.
But here my troubles started. I try to explain it. (previosly, Sorry for bad english, i still learn this language)
Lets create login window (imagine that fxml file and controller created :) ):
// some package
// some imports
public class WindowLogin extends Application{
private Stage stage;
#Override
public void start(Stage primaryStage) throws Exception {
stage = new Stage();
try {
URL location = getClass().getResource("../views/WindowLogin.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
Parent root = (Parent) fxmlLoader.load(location.openStream());
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void show(){
launch();
}
}
So, when user open application, client will try connect to server.
If connection success, then server ask client for auth (Show login window). Next - user enter login and pass and click "Login" button. (Login Window show some indication of proccess). If auth success - Hide login, else - show some info in window.
As a result, i need access from Listener to Login window Controller. i.e. as i wrote before - different answer from server - different elements displayed.
How i can realize access to LoginWindowController ?
Thanks in advance
I will give you basic guidance for each task:
Connection
If connection with the server is successful then:
Platform.runLater(new Runnable() {
public void run() {
try {
WindowLogin login = new WindowLogin();
login.start(new Stage());
} catch (Exception e) {
e.printStackTrace();
}
}
});
Login
Error
You set a blank label on the WindowController and if the user cound't autheticate, than you fill this label.
Succesful login
You could use the same Platform.runLater as I used it before, or you could do something using stackpane and changing it's order ( I strongly recommend to use the Platform.runLater).
I am writing a code that enters the username and password into a URL and submits that page. but I keep getting this error
"Caused by: org.openqa.selenium.remote.ErrorHandler$UnknownServerException:
Unable to locate element: {"method":"name","selector":"username"}"
Below is the code
package org.openqa.selenium.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class LoginPage {
private final WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
// Check that we're on the right page.
if (!"Outreach Configuration".equals(driver.getTitle())) {
// Alternatively, we could navigate to the login page, perhaps logging out first
throw new IllegalStateException("This is not the login page");
}
}
// The login page contains several HTML elements that will be represented as WebElements.
// The locators for these elements should only be defined once.
// By usernameLocator = By.name("username");
// By passwordLocator = By.name("password");
// By loginButtonLocator = By.name("submit");
// The login page allows the user to type their username into the username field
public LoginPage typeUsername(String username) {
// This is the only place that "knows" how to enter a username
driver.findElement(By.name("username")).sendKeys(username);
// Return the current page object as this action doesn't navigate to a page represented by another PageObject
return this;
}
// The login page allows the user to type their password into the password field
public LoginPage typePassword(String password) {
// This is the only place that "knows" how to enter a password
//driver.findElement(passwordLocator).sendKeys(password);
driver.findElement(By.name("password")).sendKeys(password);
// Return the current page object as this action doesn't navigate to a page represented by another PageObject
return this;
}
// The login page allows the user to submit the login form
public HomePage submitLogin() {
// This is the only place that submits the login form and expects the destination to be the home page.
// A seperate method should be created for the instance of clicking login whilst expecting a login failure.
// driver.findElement(By.name("submit")).submit();
// Return a new page object representing the destination. Should the login page ever
// go somewhere else (for example, a legal disclaimer) then changing the method signature
// for this method will mean that all tests that rely on this behaviour won't compile.
return new HomePage(driver);
}
// The login page allows the user to submit the login form knowing that an invalid username and / or password were entered
public LoginPage submitLoginExpectingFailure() {
// This is the only place that submits the login form and expects the destination to be the login page due to login failure.
// driver.findElement(By.name("submit")).submit();
// Return a new page object representing the destination. Should the user ever be navigated to the home page after submiting a login with credentials
// expected to fail login, the script will fail when it attempts to instantiate the LoginPage PageObject.
return new LoginPage(driver);
}
// Conceptually, the login page offers the user the service of being able to "log into"
// the application using a user name and password.
public HomePage loginAs(String username, String password) {
// The PageObject methods that enter username, password & submit login have already defined and should not be repeated here.
typeUsername(username);
typePassword(password);
return submitLogin();
}
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
// And now use this to visit Google
driver.get("URL Goes Here");
LoginPage login = new LoginPage(driver);
HomePage a=login.loginAs("username","Password");
}
}
I reffered it from http://code.google.com/p/selenium/wiki/PageObjects
Try to add
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
before HomePage a=login.loginAs("username","Password");.
It is not quite good approach, but it will help to find out where is the problem. This is just a pause before next step. You shouldn't use it in future, because it is not pretty good practice. It is better to use wait for condition check this out for more information.
in my web application I have register form for new user. There is also one field username:
TextField<String> username = new TextField<String>("username");
username.add(UsernameValidator.getInstance());
when user push button then username is validate. But this behaviour is not user friendly. Is there some options how to validate this dynamically and if there is error in validation user cant push button ?
You can use the: OnChangeAjaxBehavior
username.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget target) {
//do stuff here
}
});