Exceptions or null in java - java

I have the next doubt. According to good practices of java, how to manage the cases in which the object can not be found and we want to know why.
For example, if someone has problems logging in our system and we want to inform them exactly what is the problem, we cannot return null because we lose the reason for not being able to log in. For example:
public User login(String username, String password) {
boolean usernameEmpty = (credentials.getUsername()==null || credentials.getUsername().isEmpty());
boolean passwordEmpty = (credentials.getPassword()==null || credentials.getPassword().isEmpty());
//getUserPassword return null if doesn't exist an user with username and password return null
User user = getUserPassword(username,password);
if (!usernameEmpty && !passwordEmpty && user!=null) {
LOGGER.info("Found " + username);
} else if (!usernameEmpty && !passwordEmpty && user==null) {
LOGGER.info("There is no such username and password: " + username);
} else if (usernameEmpty) {
LOGGER.info("Username can not be empty ");
} else if (passwordEmpty) {
LOGGER.info("Password can not be empty ");
}
return user;
}
I can think of two options with pros and cons to resolve it.
The first one consists in using Exceptions but I think that is not a good idea use different scenarios than expected like exceptions. For that reason, I discard it.
The second one is involve the object (User) in another object to manage the differents posibilities. For example, use something like this:
public class EntityObject<t> {
//Is used to return the entity or entities if everything was fine
private t entity;
//Is used to inform of any checked exception
private String exceptionMessage;
//getters / setters / ..
}
public EntityObject<User> login(String username, String password) {
boolean usernameEmpty = (credentials.getUsername()==null || credentials.getUsername().isEmpty());
boolean passwordEmpty = (credentials.getPassword()==null || credentials.getPassword().isEmpty());
User user = getUserPassword(username,password);
EntityObject<User> entity = null;
if (!usernameEmpty && !passwordEmpty && user!=null) {
LOGGER.info("Found " + username);
entity = new EntityObject<User>(user);
} else if (!usernameEmpty && !passwordEmpty && user==null) {
entity = new EntityObject<User>("There is no such username and password: " + username);
} else if (usernameEmpty) {
entity = new EntityObject<User>("Username can not be empty ");
} else if (passwordEmpty) {
entity = new EntityObject<User>("Password can not be empty ");
}
return entity;
}
I like more this second option than the first one but i don't like that i have to change the method signature to return a different class (EntityObject) than the usual (User).
What is the usual? How is it usually managed?
many thanks

An exception should be used when there is something exceptional happening in the system. For a normal flow and something that is expected to happen you should avoid using exceptions.
Following the good SOLID principals your method should do just one thing. So if it is a method to find user by username and password I would say the best would be to return null (or empty optional if using optionals). The reason is not lost. Actually it is pretty clear - there is not such user found with the supplied username and password (this reason includes the problem with empty username and it's the user of the method's fault to supply empty username to a login method). Adding complex logic to the method and additional entities for such things will make your code harder to maintain and to understand. This method's job is not to handle validation anyway.
If that class is used by a website or its some kind of API then they can handle the validation (if username or password is empty).

For me, second options look better. Probably, to know what was the error instead of writing messages in java code, you can create enum with possible scenarios and resolve it in the Front-end code, if you really need a message, you can create constructor inside enum to store it. It will simplify support and work with an object in the future. Plus, adding more scenarios will not hurt you much.
Basic version:
public class EntityObject<t> {
//Is used to return the entity or entities if everything was fine
private t entity;
//Is used to inform of any checked exception
private enum auth {
NO_PASSWORD, NO_USERNAME, USER_DOES_NOT_EXIST, SUCCESS
}
}
Version with enum constructor:
public class EntityObject<t> {
//Is used to return the entity or entities if everything was fine
private t entity;
//Is used to inform of any checked exception
private enum auth {
NO_PASSWORD("Password cannot be empty"),
NO_USERNAME("Username cannot be empty"),
USER_OR_PASSWORD_DOES_NOT_EXIST("No such username or password exist"),
SUCCESS("OK");
public String message;
public auth(String message) {
this.message = message;
}
}
}

I would say that the second approach is pretty fine. If I were you I would do that.
If you really don't want to change the return value, you can add another method that checks if a user can log in:
public static final String SUCCESS = "Success"
public String checkLoginError(String username, String password) {
// do all the checks and return the error message
// return SUCCESS if no error
}
Now the login method can then be one line:
return getUserPassword(username,password);
And you can use it like this:
String loginResult = checkLoginError(...);
if (loginResult.equals(SUCCESS)) {
User loggedInUser = login(...)
} else {
// do stuff with the error message stored in loginResult
}

It seems like your problem is stemming from a method which is responsible for multiple concerns.
I'd argue that the login method shouldn't be checking whether these values are blank. There is presumably some kind of UI (graphical or not) which is taking a username and password - this should be the layer performing validation on the user input.
The login method should only be concerned with whether the given credentials match a user in your system or not. There's only two outcomes - yes or no. For this purpose, you can use Optional<User>. It should tolerate the strings being empty as this will never match a user anyway (presumably it's impossible for a user to exist in such a state).
Here's some pseudo-code:
void loginButtonPressed()
{
if (usernameTextBox.text().isEmpty())
{
errorPanel.add("Username cannot be blank");
}
else if (passwordTextBox.text().isEmpty())
{
errorPanel.add("Password cannot be blank");
}
else
{
login(usernameTextBox.text(), passwordTextBox.text());
// assign above result to a local variable and do something...
}
}
public Optional<User> login(String username, String password)
{
Optional<User> user = Optional.ofNullable(getUserPassword(username, password));
user.ifPresentOrElse(
user -> LOGGER.info("Found " + username),
() -> LOGGER.info("Not found")
);
return user;
}

Java's null values are one of the worst aspects of the language, as you cannot really tell if a method is receiving a null value until it happens. If you are using an IDE (I hope so) you can check if it can control whether you are passing a null value where there shouldn't be one (IntelliJ can do this by adding the #NotNull annotation to the method's parameters).
Since it can be dangerous, it is better to avoid passing nulls around, as it will certainly lead to an error as soon as your code gets a bit complex.
Also, I think it would be reasonable to check for null values only if there is a concrete chance that there could be one.
If you want to express that a value can be present or not, it's better to use Optional<T>. If, for some reason, a null value could be passed instead of a real value, you could create an utility method whose only concern is to verify that the parameters are correct:
public Optional<EntityObject<User>> login(String username, String password) {
//isNotNull shouldn't be necessary unless you can't validate your parameters
//before passing them to the method.
//If you can, it's not necessary to return an Optional
if (isNotNull(username, password)) {
//Since I don't know if a password must always be present or not
//I'm assuming that getUserPassword returns an Optional
return Optional.of(new EntityObject<User>(getUserPassword(username,password).orElse(AN_EMPTY_USER)));
} else {
return Optional.Empty();
}
}
Anyway, I think that validating the input shouldn't be a concern of the login method, even if you don't want to use Optional; it should be done in another method instead.

Related

As a library author, is it poor design to expect users to pass null to method parameters based on the situation? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I'm attempting to write a library which will be used by external users, and I'm stuck on some basic design decisions.
I'm writing a simple POJO class which will hold some information regarding OAuth2 token.
This class will need to meet the following conditions:
If the token is a permanent token, the user needs to pass only the token.
If the token in a temporary token, the user needs to pass the token, expirationDate, and the refreshToken.
There will never be a scenario where only one of expirationDate and refreshToken will be null. Either both will be null or both will be non-null.
This is what I have so far:
public TokenInformation(String token, Date expirationDate, String refreshToken) {
Objects.requireNonNull(token, "token parameter cannot be null.");
this.token = token;
if ((expirationDate != null) && (refreshToken != null)) {
this.expiresIn = expiresIn;
this.refreshToken = refreshToken;
isPermanentToken = false;
} else if ((expirationDate == null) && (refreshToken == null)) {
this.expiresIn = null;
this.refreshToken = null;
isPermanentToken = true;
} else {
// throw some exception here
}
}
To be honest, I'm not entirely happy with the way the code looks.
But I did have the following ideas:
Have two constructors. One with only one parameter (for permanent token) and the other with all three parameters (temporary token). However, my concern is that users will not read the documentation properly and will use the permanent token constructor for a temporary token.
Have two different factory methods instead of constructors. These factory methods will be clearly named and so the chances of a user using the wrong method will be slim. Additionally, the user will not be forced to explicitly pass in null.
I think the second idea might be the best approach. For instance, I can't think of any Java APIs which require us to pass null and that might be a hint that the code I pasted is a bad idea. Additionally, Java makes use of factory methods quite a bit, and so it's won't be an unfamiliar pattern for users of my library.
I would like other people's opinions though. So please let me know if you need any other information.
I would prefer to encapsulate the Permanent and Temporary token behavior into their respective domains so any user of your library clearly knows what kind of token is being instantiated
Suggested classes in my opinion:
/**
* The base class encapsulates the behavior of generic token
*/
public class AbstractToken {
protected String token;
// other properties that exist very closely with token
public String getToken() {
return token;
}
}
Domain for Permanent Token
/**
* The domain encapsulates the behaviour of Permanent token - token that never expires
*/
public class PermanentToken extends AbstractToken {
// more attributes that makes general token as Parmament token
/**
* Instantiates a new Permanent token - this token never expires
*
* #param token the token
*/
public PermanentToken(String token) {
this.token = token;
}
}
Domain for Temporary Token:
/**
* The domain for Temporary token.
*/
public class TemporaryToken extends AbstractToken {
private Date expirationDate;
private String refreshToken;
// more attributes that makes general token as temporary token
/**
* Instantiates a new Temporary token with token expiry date and refresh token
*
* #param token the token
* #param expirationDate the expiration date
* #param refreshToken the refresh token
*/
public TemporaryToken(String token, Date expirationDate, String refreshToken) {
this.token = token;
this.expirationDate = expirationDate;
this.refreshToken = refreshToken;
}
}
Now the user of your library clearly knows what kind of token he/she wants to instantiate and use.
P.S. - I guess you would be able to keep better names for your domains
and you as deep into the business for your library.
Based on your code above, I think the multiple constructor approach is more appropriate than the factory. It is a very common Java design pattern to have multiple constructors on which the user can pass in the information for just fields they do have data for. The constructors wouldn't duplicate code, but rather they would call eachother with the default values.
public TokenInformation(String token) {
this(token, null, null);
}
public TokenInformation(String token, Date expirationDate, String refreshToken) {
Objects.requireNonNull(token, "token parameter cannot be null.");
this.token = token;
if ((expirationDate != null) && (refreshToken != null)) {
this.expiresIn = expiresIn;
this.refreshToken = refreshToken;
isPermanentToken = false;
} else if ((expirationDate == null) && (refreshToken == null)) {
this.expiresIn = null;
this.refreshToken = null;
isPermanentToken = true;
} else {
// throw some exception here
}
}
Since you don't have multiple different types of TokenInformation objects being created, I don't find the factory pattern to fit your needs. If you were to use a pattern, I would go with Builder instead of factory.
EDIT: I should have read your code better. I'll leave my answer here because I think my solution is still applicable if you don't want to change your classes, but, I think #DHRUV BANSAL has the overall better better approach since your tokens are actually representing different things

Java - Should I read a value in setter?

I have a setter which I want it to check if an email address contains the characters "#" and "." , before setting the value. If the email address does not contain these characters I want the user to enter the email address again. Should I read the new value inside the setter or is it bad pracice and should only be done in main or in a different method?
import java.util.Scanner;
public class Person {
private String emailAddress;
Scanner input = new Scanner( System.in);
public void setEmail(String email)
{
while(email.indexOf('#')<0 || email.indexOf('.')<0)
{
System.out.println("The email address must contain the characters \"#\" and \".\" ");
System.out.println("Enter email address again:
email = input.nextLine();
}
}
}
No, this is bad practice.
The problem is that you will get stuck if you call the method in a context where you don't have an interactive console, e.g. in a unit test.
Throw an IllegalArgumentException, and let the caller implement the retry (or not).
In your setter:
void setEmail(String email) {
if (!email.contains("#") || !email.contains(".")) {
throw new IllegalArgumentException("Invalid email: " + email);
}
this.emailAddress = email;
}
In your caller:
while (true) {
try {
setEmail(emailAddress);
break;
} catch (IllegalArgumentException e) {
// Show a message, or whatever.
}
You are mixing functionality and responsibilities here in a bad way.
Yes, the setter should absolutely validate input, this is one of the most common reasons to utilize an accessor method instead of exposing the variable itself.
No, the setter should not make use of System.in or System.out to request new input from the user. Leave that up to main or what have you. This is outside of the scope of the setter's (and Person class' responsibilities)
The best methodology here is to use the IllegalArgumentException and let the calling code handle that as it wishes.
public void setEmail(String email)
{
if(email.indexOf('#')<0 || email.indexOf('.')<0)
{
throw new IllegalArgumentException("Invalid email address.");
}
this.email = email;
}
Your client code could then utilize it like so
boolean goodEmail = false;
while (!goodEmail) {
String inputEmail = getTheEmailAddressFromTheUserSomehow();
try {
person.setEmail(inputEmail);
goodEmail = true;
} catch (IllegalArugmentException e) {
//try again!
//or don't, depends on the workflow of the application
}
}
In general it's a bad idea if a method does anything other than its name suggests.
If the method is called setFoo(), people expect it to update the field called foo and do nothing else. Of course you can (indeed you should) validate your input and throw an IllegalArgumentException if it isn't what you want, but nothing else.
This is often called "the principle of least surprise" and it's a very useful design principle for writing code.
Another general rule of thumb is that as much as possible, methods should be only responsible for one thing.
Of course what's a "thing" will vary, it could be something very specific (for example: "this method multiplies the two parameters") or it could be more general ("this method handles all my input"), but if you can't explain in a simple sentence what the method does, it probably does too much.
(As an exercise, think about how you'd explain to a friend what setEmail() does. Say the words out loud. It really works.)
This is even more important when you're doing I/O, like you do in your example: it should be very-very clear who reads from the Scanner and when, otherwise it becomes practically impossible to follow what input is expected at what stage of the program. In this case even your Person class shouldn't do anything with the Scanner. Handle the input somewhere else and leave the Person class to just represent a person.

if username and password combination are correct by checkin the google datastore

Edit: Apparently the question wasn't clear so...
How do I find the password for a user in the datastore and check if it is equal to the password given to the method if that makes sense.
end of edit.
I have the following code for checking if the username exists, now I just need to check the password is correct for the given username.
public boolean Login(String usernamein, String passwordin) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Filter usernamefilter = new FilterPredicate("username", FilterOperator.EQUAL, usernamein);
Query validuserquery = new Query("Users").setFilter(usernamefilter).setKeysOnly();
Entity theUser = datastore.prepare(validuserquery).asSingleEntity();
System.out.println(usernamein);
System.out.println(validuserquery);
System.out.println(theUser);
if(theUser == null) {
System.out.println("Username not found");
return false;
}
return true;
}
I am struggling to work out how I would do this even as pseudo code and I am really new to GAE and datastore but its for my A-Levels
I thought this addition would do it but theUser.getProperty("password") is null i don't really know what the user is in this code but i do know all the users in my data store have a password so none of them should be null
if(theUser == null) {
System.out.println("Username not found");
return false;
}
System.out.println(theUser.getProperty("password"));
if(passwordin.equals(theUser.getProperty("password"))){
return true;
}
return false;
If anything doesnt make sense or if you need more info tell me please as i do really need help :(
The setKeysOnly was my suggestion on a separate Q (and you haven't accepted my A there so it's, ahem, peculiar to see you use it here!) where you wanted just to check if the username was present or not.
With that you don't get any properties.
Remove it and the properties will be there (in your first Q you had a projection, which is fine if your user entity is large and you only need the password property out of many -- but it's an optimization, just like setKeysOnly is, and you hopefully know the rule -- first make it work, then make it fast!-).

How to not return anything for a method with return type int

public static int logIn(Statement stmt){
int id;
String pw;
String select;
boolean match;
System.out.print("userID: ");
id = input.nextInt();
input.nextLine();
System.out.print("password: ");
pw = input.next();
input.nextLine();
select = "SELECT user_id, password FROM login WHERE user_id = " + id;
try{
ResultSet rs = stmt.executeQuery(select);
while(rs.next()){
if(id == rs.getInt(1) && pw.equals(rs.getString(2))){
match = true;
}
}
}
catch(SQLException logfail){
logfail.printStackTrace();
System.out.println("could not print password");
}
if(match == true)
return id;
else break;
}
In my program, the user will input their login info. Then they will be faced with a menu in which they select options 1-7. Options 1-7 are just various queries that will be run on their own data.
My login function is to verify that they are who they are, as to give them access to their own data. If the verification passes, I return the id number in which they entered so that I may pass it into the other functions (1-7).
In my if-else statement, I want it to return the id number if the passwords matched and to return null if it failed.
I know that int can't be null but my return type for this method is int so what can I do?
For the sake of timely completion of my assignment, I'm going to return a value of 0 if things don't match to indicate that the login failed. But, more important to me is becoming a good Java programmer so I want to know:
Is there a better way to do this? and
Since there is, what can I do and how?
Thanks!
The easiest change you can make is to return Integer and return null. Integer is an object, that's why you can do this.
Alternatively, you could throw an exception if it is an error to not be able to login. It probably isn't an exceptional case, so this may not be the best way.
Probably the best thing you could do is to not return an int/Integer. Instead, have a class that represents the thing to do next.
Returning zero, or a negative value like -1 is one possibility. You can also create a checked exception LoginException which is thrown in case of invalid login credentials. The pro of this approach is that you have a nice way to log fault login attempts within the LoginException.
Any time you declare a function with a primitive type it must return a value or throw an exception. You can use the wrapper types: Boolean,Integer,Long,etc to return null because these are "real" objects in Java.
If you've declared a method of an int type, it must return an int. Simply declare/define an invalid_return variable which will be returned in case no match is found, simple as that.
When a method has a return type of int, then you must return an int. To indicate that an error occurred, you can either return an value which is otherwise invalid or throw an Exception.
The best way to not return from a method is to throw an exception instead. Returning error values like null or zero leads to buggy code when people forget to check for them. An exception is unambiguous and can't be ignored.
Really to be sensible you should separate your return numbers from you query by placing the two in different methods.
To return null, you need to return a class such as an ADT(Abstract Data type) from a method.
However that may be over-complicated when you can simply flag 0 zero as null with a variable of class Integer that you reset to null before each use, so if it is zero returned you only need put in an if-else to test the "Integer" variable as null or contains resetting to a number returned as int from the method.

Non-Confusing Simple Validation of email in Java String

I am trying to find a simple method to check to see if a user's input meets a couple criteria for an email address. I've read through many threads on this subject and most seem to want to validate the email address too. I'm not trying to build some super duper email address validator/checker. I'm trying to build a method that checks for these things:
The string entered by the user contains the '#' sign.
There are at least two characters before the '#' sign.
There is a '.' after the at sign followed by only three characters. The domain name can be as long as needed, but the string must end with "._ _ _". As in ".com" or ".net"...
I understand that this is not an all encompassing email address checker. That's not what I want though. I want just something this simple. I know that this is probably a routine question but I can't figure it out even after reading all of the seriously crazy ways of validating an email address.
This is the code I have so far: (Don't worry I already know it's pretty pathetic.... )
public static void checkEmail()
{
validEmail(emailAddresses);
if(validEmail(emailAddresses))
{
}
}
public static boolean validEmail(String email) {
return email.matches("[A-Z0-9._%+-][A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{3}");
}
The javax.mail package provides a class just for this: InternetAddress. Use this constructor which allows you to enforce RFC822 compliance.
Not perfect, but gets the job done.
static boolean validEmail(String email) {
// editing to make requirements listed
// return email.matches("[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2,4}");
return email.matches("[A-Z0-9._%+-][A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{3}");
}
void checkEmails() {
for(String email : emailAddresses) {
if(validEmail(email)) {
// it's a good email - do something good with it
}
else {
// it's a bad email - do something... bad to it? sounds dirty...
}
}
}
int indexOfAt = email.indexOf('#');
// first check :
if (indexOfAt < 0) {
// error
}
// second check :
if (indexOfAt < 2) {
// error
}
// third check :
int indexOfLastDot = email.lastIndexOf('.');
if (indexOfLastDot < indexOfAt || indexOfLastDot != (email.length() - 4)) {
// error
}
Read http://download.oracle.com/javase/6/docs/api/java/lang/String.html for the documentation of the String methods.

Categories

Resources