if i have something like this:
public User findUserByEmail(String email) throws CustomerNotFoundException{
List<User> users = new ArrayList<User>();
users = sessionFactory.getCurrentSession().createQuery("from User where email = ?").setParameter(0,email).list();
if (users.size() > 0) {
return users.get(0);
} else {
throw new CustomerNotFoundException();
}
}
And in this moment i want to check the returned findUserByEmail(String email) method whether it return the User object or CustomerNotFoundException in the end.
I tried in this way
private boolean searchCustomer(String email) throws CustomerNotFoundException{
if (hibernateDao.findUserByEmail(email).getClass() == User.class) {
....
} else { .... }
}
Is it a good way or are there betters?
No. Nonononono.
Use the catch keyword to catch the Exception.
try {
User thingie = hibernateDao.findUserByEmail(email);
}
catch (CustomerNotFoundException cnfe) {
// TODO some logic on failure
}
Also remove the throws statement from your searchCustomer method's signature if you're using a try / catch mechanism and not rethrowing the Exception.
Related
Can this func. not be prettified?
Can the the catch clause be left empty, I have heard it's frowned up on.
apiClient.accountList() is where the exception can occur.
public Optional<Account> getAccount(String accountUuid) throws ApiException {
try {
for (Account account : apiClient.accountList()) {
if (account.getUuid().equals(accountUuid)) {
return Optional.of(account);
}
}
} catch (ApiException e) {
return Optional.empty();
}
return Optional.empty();
}
If you're very motivated to avoid the duplicate return statement, a simple tweak to the control-flow should do it. As mentioned in the comments, logging exceptions is often a good idea.
public Optional<Account> getAccount(String accountUuid) throws ApiException {
Optional<Account> result = Optional.empty();
try {
for (Account account : apiClient.accountList()) {
if (account.getUuid().equals(accountUuid)) {
result = Optional.of(account);
break;
}
}
}
catch (ApiException e) { /* Log exception */ }
return result;
}
You can use Stream, assuming getUuid does not throw an ApiException.
public Optional<Account> getAccount(String accountUuid) throws ApiException {
try {
return apiClient.accountList().stream()
.filter(account -> account.getUuid().equals(accountUuid))
.findAny();
} catch (ApiException e) {
/* Log exception */
return Optional.empty();
}
}
Actually instead of collection returning methods like accountList() it more and more makes sense to use Streams, accountStream().
Inside a method, a condition is needed to proceed the logic. An unhandled exception warning message shows up in my IDE. Wrapping the whole block with try-catch doesn't let the message go away.
public void changePassword(String login, String currentClearTextPassword, String newPassword) {
userRepository.findOneByLogin(login)
.ifPresent(user -> {
String currentEncryptedPassword = user.getUserSecret();
String encryptedInputPassword = "";
try {
encryptedInputPassword = authUtils.encrypt(currentClearTextPassword);
} catch (Exception ex) {
System.err.println("Encryption exception: " + ex.getMessage());
}
if (!Objects.equals(encryptedInputPassword, currentEncryptedPassword)) {
throw new Exception("Invalid Password"); // <-- unhandled exception
}
String encryptedNewPassword = "";
try {
encryptedNewPassword = authUtils.encrypt(newPassword);
} catch (Exception ex) {
System.err.println("Encryption exception: " + ex.getMessage());
}
user.setUserSecret(encryptedNewPassword);
userRepository.save(user);
log.debug("Changed password for User: {}", user);
});
}
How to deal with this warning message?
Treating Exception inside stream operation is a little overhead, I would like to separate the operation and makes it like so :
public void changePassword(String login, String currentClearTextPassword, String newPassword) throws Exception {
//get the user in Optional
Optional<User> check = userRepository.findOneByLogin(login);
//if the user is present 'isPresent()'
if(check.isPresent()){
//get the user from the Optional and do your actions
User user = check.get();
String currentEncryptedPassword = user.getUserSecret();
String encryptedInputPassword = "";
try {
encryptedInputPassword = authUtils.encrypt(currentClearTextPassword);
} catch (Exception ex) {
throw new Exception("Encryption exception: " + ex.getMessage());
}
if (!Objects.equals(encryptedInputPassword, currentEncryptedPassword)) {
throw new Exception("Invalid Password"); // <-- unhandled exception
}
String encryptedNewPassword = "";
try {
encryptedNewPassword = authUtils.encrypt(newPassword);
} catch (Exception ex) {
throw new Exception("Encryption exception: " + ex.getMessage());
}
user.setUserSecret(encryptedNewPassword);
userRepository.save(user);
log.debug("Changed password for User: {}", user);
}
}
Beside the Exception should be thrown not just printed.
Like #louis-wasserman said you can use an unchecked exception.
So instead of
throw new Exception("Invalid Password");
use:
throw new RuntimeException("Invalid Password"); // for example
Note: It is better to use a custom RuntimeException that fits your use case.
For the general case, #pari-ngang is correct: within a lambda expression you cannot handle a checked exception outside the calling function. Either use an unchecked or use the try construct in the lambda.
However, needing to do either of these might be a sign of poor structure. Having a large block of code within a lambda is one such sign. Here are a few suggestions for your specific case:
1. As a simplification of #ycf-l's answer, invert the logic and simply return user if not found:
Optional<User> user = userRepository.findOneByLogin(login);
if (!user.isPresent()) {
return;
}
// ... carry on as before outside of a lambda
2. Seperate the logic of fetching the user from changing the password of a user (you'll still have to pass exceptions back up):
if (user.isPresent()) {
changePassword(user.get(), currentClearTextPassword, newPassword);
}
3. You can also use libraries like vavr to simplify the try/catch blocks:
String encryptedInputPassword = Try.of(() -> authUtils.encrypt(currentClearTextPassword))
.onFailure(e -> System.err.println("Encryption exception: " + e.getMessage()))
.orElse("");
4. If you're willing to pursue vavr, you can also solve the more general problem:
userRepository.findOneByLogin(login)
.map(user -> Try.of(() -> {
// Your change password stuff goes here.
changePassword(user, currentClearTextPassword, newPassword);
return null; // I don't currently know of any way of passing a runnable.
}))
// This pulls the exception out of the lambda function, satisfying the compiler.
.orElseGet(() -> Try.success(null))
.getOrElseThrow(Function.identity());
I haven't used vavr much so can't tell you if this is the most efficient/cleanest approach/use of vavr, but it will solve your problem.
In the try block, I am hoping that the status variable will change to true and a successful return will be sent. I do not want to send false return type.
Instead, I want to throw error if return type would be false. Can i have a situation where a false return type is sent.
public boolean updateSchool(String username, String password, String school) throws Exception {
User user = userDao.findByUsername(userName);
boolean status = false;
try {
if (user != null && user.getPassword().equals(password)) {
user.setSchool(school);
userDao.save(user);
status = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return status;
}
You can try something like this,
public boolean updateSchool(String username, String password, String school) throws Exception {
User user = userDao.findByUsername(userName);
boolean status = false;
try {
if (user != null && user.getPassword().equals(password)) {
user.setSchool(school);
userDao.save(user);
status = true;
}
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Could not update School.");
}
finally{
if(!status){
throw new Exception("status is false");
}
}
}
return status;
}
there are two "problems":
there is no sense to re-throw exception
there is no sense in constant return value
its better to write something like this:
public void updateSchool(String username, String password, String school) throws Exception {
User user = userDao.findByUsername(userName);
if (user != null && user.getPassword().equals(password)) {
user.setSchool(school);
userDao.save(user);
}
}
this method either finish successfully or throw exception in case of error
I've got a method which throws an exception itself and calls a method which catches another exception:
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (authenticated()) {
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
} else {
return null;
}
}
private boolean authenticated(){
try {
thirdPartyClass.login();
return true;
} catch (ThirdPartyException e) {
return false;
}
}
thirdPartyClass.login() is from an api I don't own and it is a void method so all unsuccessful authentications must be catched.
ThirdPartyException exception gives a good explanation of what went wrong so I'd like to have it as my error message instead of:
No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken
which comes from AuthenticationException
How can this be achieved?
What about something along these lines:
public Authentication authenticate(Authentication authentication)
throws AuthenticationException
{
try {
thirdPartyClass.login();
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
} catch (ThirdPartyException tpe) {
throw new AuthenticationException(tpe.getMessage(), tpe);
}
}
Do you want to get message from ThirdPartyException? If so, then you can do something like:
private boolean authenticated() throws ThirdPartyException {
thirdPartyClass.login();
return true;
}
if not, then kindly explain it
Updated
public Authentication authenticate(Authentication authentication)
throws AuthenticationException
{
try {
authenticated();
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
} catch (ThirdPartyException ex) {
throw new AuthenticationException(ex.getMessage(), ex);//or any other child exception of AuthenticationException
}
}
Just replace the function with this code:
private boolean authenticated(){
try {
thirdPartyClass.login();
return true;
} catch (ThirdPartyException e) {
return false;
} catch (Exception ex) {
return false;
}
}
If the thirdPartyClass.login(); is handling the exception and printing error on console then you can only ignore the message, and consider that thirdParty function is telling you that username and password tokens are not valid ones.
I am building a java REST application. Therefor I am using jboss on a wildfly 8 server.
The following code causes this exception: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
#Path("/users")
#Stateless
public class UsersEndpoint {
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response create(User user) {
try {
this.checkUsername(user.getUsername());
this.checkEmail(user.getEmail());
return Response.ok(userDAO.create(user)).build();;
} catch (IOException e) {
return Response.status(Response.Status.NOT_ACCEPTABLE)
.entity(e.getMessage())
.build();
} catch (Exception e) {
return Response.status(Response.Status.NOT_ACCEPTABLE)
.entity(e.getMessage())
.build();
}
}
#POST
#Path("username")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.TEXT_HTML)
public Response username(String username) {
try {
this.checkUsername(username);
return Response.ok().build();
} catch (Exception e) {
return Response.status(Response.Status.NOT_ACCEPTABLE)
.entity(entity)
.build();
}
}
#POST
#Path("email")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.TEXT_HTML)
public Response email(String email) {
try {
this.checkEmail(email);
return Response.ok().build();
} catch (Exception e) {
return Response.status(Response.Status.NOT_ACCEPTABLE)
.entity(this.validator.validateError(null, e))
.build();
}
}
private void checkUsername(String username) throws IOException {
try {
userDAO.get(username);
throw new IOException("Username is taken allready.");
}
catch (IOException e) { throw e; }
catch (Exception e) { System.out.println("Username can be used"); }
}
private void checkEmail(String email) throws IOException {
try {
userDAO.getByEmail(email);
throw new IOException("Email is taken allready.");
}
catch (IOException e) { throw e; }
catch (Exception e) { System.out.println("Email can be used"); }
}
}
The public Response email(String email) and public Response username(String username) functions are working fine. The Problem seems to be the call of both functions through the public Response create(User user) function:
...
try {
this.checkUsername(user.getUsername());
this.checkEmail(user.getEmail());
...
So now when I have a correct username but a duplicate email the exception JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context) is going to be thrown in the userDAO.getByEmail(email). When I have a duplicate username instead the IOException("Username is taken allready.") is going to be thrown as expected.
When I change the order of those functions to:
...
try {
this.checkEmail(user.getEmail());
this.checkUsername(user.getUsername());
...
the same problem occurs but in userDAO.get(username) and with a correct email and a duplicate username.
EDIT
When I am removing throw new IOException("Username is taken allready."); in private void checkUsername(String username) throws IOException { } the second DAO call is working fine. So the problem seems to be the Exception that is thrown. How can I solve that?
My UserDAO
public interface UserDAO {
public User create(User user) throws Exception;
public User get(String username) throws Exception;
public User getByEmail(String email) throws Exception;
}
My UserBean
#Stateless
#Remote(UserDAO.class)
public class UserBean implements UserDAO {
// Injected database connection:
#PersistenceContext private EntityManager em;
#Override
public User create(User user) throws Exception {
em.persist(user);
return user;
}
#Override
public User get(String username) throws Exception {
return em.createNamedQuery(User.QUERY_USERNAME, User.class)
.setParameter("userName", username)
.getSingleResult();
}
#Override
public User getByEmail(String email) throws Exception {
return em.createNamedQuery(User.QUERY_EMAIL, User.class)
.setParameter("email", email)
.getSingleResult();
}
}