Can't compare Strings - spring

I am not able to compare the String returned from student.getUsername() to the hardcoded string(it is alway false even for correct values)
but when I use a normal string and not the one returned from student.getUsername() it is able to execute if block and return "login Success". I think the value returned from student.getUsername() is not comparable to String I even tried .toString() but no luck Please help.
#PostMapping()
public String setUser(#Valid #ModelAttribute("Student")Student student, Errors errors,
ModelMap model) {
String user = "das";
String pass = "12345";
if((student.getUsername()==user)&&(student.getPassword()==pass))return "loginSuccess";
else return "loginFailure"

You should use equals() method to compare the CONTENT of strings.
== operator in Java compares addresses of objects not theirs content :<

Related

Getting and Setting values in java 8 using optional and map

I am trying to use Optional instead of standard null checks in java
#Data
public class InputObj {
private Double savings;
}
#Data
public class Result {
private String outputSavings;
}
public Result convertInputObjToResult(InputObj inputObj){
Result result = new Result();
Optional<InputObj> optionalInputObj = Optional.ofNullable(inputObj);
optionalInputObj.map(InputObj::getSavings).map(value -> util.convertRoundAndAbs(value,true)).ifPresent(result::setOutputSavings);
return result;
}
which is equivalent of below
public Result convertInputObjToResult(InputObj inputObj){
Result result = new Result();
if(inputObj != null){
if(inputObj.getSavings() != null){
result.setOutputSavings(util.convertRoundAndAbs(inputObj.getSavings(),true));
}
}
return result;
}
I wrote some test cases and I do not get any Null Pointer Exception but I am unable to understand that ifPresent condition is at end and map is before but still I don't get any NPE. Do you see any thing wrong with this code or how it can be improved? This is part of a spring boot application and #Data annotation is used for lombok.
Here's a link to further describe how the map operation works for the Java Optional class.
If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.
So in a case where you have a null value from the map method, it will automatically be converted to Optional.empty().
Then, taking a look at the ifPresent method
If a value is present, invoke the specified consumer with the value, otherwise do nothing.
So this is why you aren't getting any NPE's; the map operations are able to map null results or passed values to Optional.empty(), and the ifPresent operation doesn't execute if passed an empty Optional.
There is no issue with the code except for the typo “ optionalMembershipDetails”. Assuming you meant to use “ optionalInputObj”.
You need to read about java streams to understand the full concept. In a nutshell, operations are evaluated in lazy manner. So ifPresent call will trigger operations which appear before it. In this case, the object is wrapped inside optional, so each intermediate operation will pass another optional to the next operation. Having Optional prevents you getting NPE.

Spring AOP get method parameter value based on parameter name

Is it possible to get the method parameter value based on parameter name in Spring AOP.
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
Method method = signature.getMethod();
method.getParameters().getName()
// possible to get the paramater names
This approach will get parameter names, not value.
proceedingJoinPoint.getArgs()
will return values not names
Then is it possible to get the value based on a parameter name?
As I searched everywhere does not exist a function that gives parameter value by name and I wrote a simple method that makes this work.
public Object getParameterByName(ProceedingJoinPoint proceedingJoinPoint, String parameterName) {
MethodSignature methodSig = (MethodSignature) proceedingJoinPoint.getSignature();
Object[] args = proceedingJoinPoint.getArgs();
String[] parametersName = methodSig.getParameterNames();
int idx = Arrays.asList(parametersName).indexOf(parameterName);
if(args.length > idx) { // parameter exist
return args[idx];
} // otherwise your parameter does not exist by given name
return null;
}
I searched for the same thing when I had to use AOP for logging function arguments and their values but it seems there is no direct way to get value based on argument name.
What I noticed however us that value returned by method.getParameters().getName() and proceedingJoinPoint.getArgs() was always in sync., i.e., for function
public void foo(String a, String b)
called as
foo("hello", "world");
method.getParameters().getName() returned ["a", "b"] and proceedingJoinPoint.getArgs() returned ["hello", "world"], in order. So you can iterate over the array by index and for each index i, the i'th argument name would correspond to i'th argument value.
I couldn't find a supporting documentation for this behavior but hey, this code has been running on production servers for about an year it never has produced incorrect result. Though I'd be glad if someone can link to a documentation of this behavior. You may even dig into reflectiion's code to verify this behavior.

How to differentiate when "second field" is missing in LocalDateTime

I am given LocalDateTime object created from String. I want to check whether that original string has "seconds" parameter or not.
My two inputs are:
String a = "2016-06-22T10:01"; //not given
String b = "2016-06-22T10:01:00"; //not given
LocalDateTime dateA = LocalDateTime.parse(a, DateTimeFormatter.ISO_DATE_TIME);
LocalDateTime dateB = LocalDateTime.parse(b, DateTimeFormatter.ISO_DATE_TIME);
Problem is I am given dateA and dateB, not a and b.
I have tried various ways like converting LocalDateTime to String and finding its length. For that I used two approaches.
date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME).length();
date.toString().length();
But first approach gives length 19 for both dateA and dateB whereas second approach gives length 16 for both dateA and dateB.
I am unable to find any way to differentiate dateA and dateB.
As other people have already said, a LocalDateTime-object has always a second part. The other question is if the original input has got a second part or not. It is possible to find out the answer with only Java-8-means (but it is ugly because it is based on exception control flow):
String a = "2016-06-22T10:01"; // not given
String b = "2016-06-22T10:01:00"; // given
boolean hasSecondPart;
try {
TemporalAccessor tacc =
DateTimeFormatter.ISO_DATE_TIME.parseUnresolved(a, new ParsePosition(0));
tacc.get(ChronoField.SECOND_OF_MINUTE);
hasSecondPart = true;
} catch (UnsupportedTemporalTypeException ex) {
hasSecondPart = false;
}
System.out.println(hasSecondPart); // true for input b, false for input a
Side note:
An exception-free check if the string input has a second part or not would be possible with my library Time4J using this code:
boolean hasSecondPart =
Iso8601Format.EXTENDED_DATE_TIME.parseRaw(a).contains(PlainTime.SECOND_OF_MINUTE);
In ISO_DATE_TIME, seconds are optional (and set to zero if not present), that's why it parses both inputs. And LocalDateTime.toString() method will print the seconds only if it's not zero.
So, once you have the LocalDateTime objects created, you can't know if the original String had the seconds field.
To validate if the seconds field is present in the input String, you must create your own pattern and check if it throws exception when parsing:
// formatter with required seconds
DateTimeFormatter withSecs = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
LocalDateTime.parse(b, withSecs); // OK
LocalDateTime.parse(a, withSecs); // DateTimeParseException
If you want just to check if the field is present, but don't want to build a LocalDateTime object, you can also use parseUnresolved method, which doesn't throw exceptions:
ParsePosition position = new ParsePosition(0);
withSecs.parseUnresolved(a, position);
if(position.getErrorIndex() == -1) {
System.out.println("No error (it contains seconds)"); // b gets here
} else {
System.out.println("Error (it does not contain seconds)"); // a gets here
}
In Java 8 DateTime API
dates can be represented in the following way:
LocalDate as year-month-day
LocalDateTime as
year-month-day-hour-minute-second
ZonedDateTime as
year-month-day-hour-minute-second with time zone
As you can see, there is no way to differentiate between year-month-day-hour-minute-second and year-month-day-hour-minute. So, after the conversion from String to LocalDateTime is done - you can't differentiate it. The only way to do this is with String (either by length or regex), not with LocalDateTime object.

spring AoP, pointcut expression for overloaded methods with same parameter types

I've defined a class for CRUD operations on comments. The read method is overloaded.
class Comment{
// method 1: returns all the comments by a user
findAll(long userId, long subjectId, String param);
// method 2: returns all the comments of all the users
findAll(long subjectId, String param)
}
The point cut expression I've tried is
#Around("execution(* com.package..*Controller.findAll(..)) && args(userId,subjectId,..)")
public Object validateFindAll(final ProceedingJoinPoint proceedingJoinPoint, final long userId, final long subjectId) {
// validate userId, if available
// validate subjectId
}
Problem: As the data types for userId and subjectId are same, the point expression when applied to method 2 shifts the param values by 1 place. This means, the expression does not understand that the first parameter userId isn't passed. Instead, userId gets 'subjectId' as value and the subjectId gets the adjacent parameter 'param' as its value.
Note
I am trying to avoid writing another method like findUserComments().
I want to maintain consistency across the application. There are other classes with similar patterns of CRUD operations.
Question: Is it possible to define an expression applicable to both the methods with the first parameter userId being optional ?
EDIT - Solution
While I was playing around with different approaches as suggested in the solutions below, I've finally removed method 2. I handle that case in method 1.
You cannot explicitly bind an AspectJ parameter and then expect it to match an incompatible signature. Thus, your pointcut will only match findAll(long, long, ..), i.e. "method 1" in your example. You can specify optional arguments with .., but then you cannot bind them to named parameters.
For example, it is possible to match both methods and bind long subjectId and String param via args(.., subjectId, param) because both parameters are predictably right-aligned at the end of the signature. If you want any optional (and thus unbound) parameter, you need to use thisJoinPoint.getArgs():
#Around("execution(* com.package..*Controller.findAll(..)) && args(.., subjectId, param)")
public Object validateFindAll(
final ProceedingJoinPoint thisJoinPoint,
final long subjectId,
final String param
) {
if (thisJoinPoint.getArgs().length == 3)
System.out.println(thisJoinPoint + " -> " + thisJoinPoint.getArgs()[0] + ", " + subjectId + ", " + param);
else
System.out.println(thisJoinPoint + " -> " + subjectId + ", " + param);
// (...)
}
But while getArgs() is dynamic, it probably is slower than parameter binding because it uses reflection. Maybe having two pointcuts is not so bad after all. If your advice method does complicated things before/after proceed(), you can still factor those things out into helper methods and call them from both advice.
Problem is related to method averloading actually. Since, you are passing long userId and long subjectId AOP will always try to match those arguments. Solutions could be
1) Create another pointcut for other argument i.e. 1 for long,long and other for long, String
2) Use variable argument signature in the begining such as
#Around("execution(* com.org..findAll(..)) && args(..,subjectId,param)")
public Object validateFindAll(final ProceedingJoinPoint joinPoint, final long userId, final long subjectId) {
}
instead of using variable argument in the begining. Then you can use getArgs() method to figure out arguments.
This is simple solution but may slowdown your processing.
3) Though as a design issue, I would suggest to encapsulate all your parameters in one single object and pass it. Instead of passing multiple parameters. It will help you in future as well.

TDD: What to test in code where is 800 and more possible outputs?

I have class that have properties IsMacro, Value, Visible, DataType and one method GetResolvedValue. I dont know what to test. I do some math and I figure out that there is over 800 possible outputs for that method.
enum DataTypeEnum:
Bool,
String,
DateTime,
Integer,
LongInteger,
Decimal,
...
class Macro
property bool IsMacro;
property string Value;
property bool Visible;
property DataTypeEnum DataType;
function GetResolvedValue(Resolver) {
string value = Value;
if (IsMacro && Visilbe) {
value = Resolver.resolve(value);
}
switch (DataType){
case String:
// returns value if is string e.g.: "text"
// othervise returns empty string
case Bool:
// returns value if is bool string e.g.: "true"
// othervise returns empty string
case DateTime:
// returns value if is DateTime string e.g.: "2/2/2010"
// othervise returns empty string
...
}
}
So it must always return string with value that is valid for associated datatype or empty string.
With this code there is a lot of combinations and I dont know how to test it. Shoud I test all posible solutions?
Listen to your tests!
Even now, before even being written, your tests tell you that this method massively violates the SRP and needs to be refactored.
You should probably extract a whole hierarchy of classes from this one method.

Resources