Spring boot how to evaluate property with square brackets [a,b,c] - spring

I am using spring-boot-1.5.19 and in my application.yml I have below the entry
sample:
image:
size-array: [280, 420, 560, 840, 1120]
I used below code to access the above property
#Value("#{'${sample.image.size-array}'.split(',')}")
public List<Integer> sizes;
But I was getting error then used below style,
#Value("#{sample.image.size-array}")
public List<Integer> sizes;
Also, I Tried with string but no luck. Any help would be really appreciated.

You can use the below Spel Exp for parsing the data into a list:
#Value("#{'${sample.image.size-array}'.replace('[', '').replace(']', '').split(',')}")
private List<Integer> sizes ;

Related

Java: Multiply two list which are Stream<BigDecimal>

I know my Question is a little for beginners, but in Internet I didn't find Answer, So It's good to have,
I have a list which contain two value, first an Enum Type, second a big decimal Number. In my Enum Class, I have also two values related to each Enum, the first value is a string and the second is a BigDecimal.
Enum:
private enum myEnumClass {
BMW("Karl Rapp", new BigDecimal("1916")), BENZ("Carl Benz", new BigDecimal("1926")),
private String founder;
private BigDecimal yearOfFoundation;
List:
List<CarDetails> numberOfcars = new ArrayList<>();
numberOfcars.add(new CarDetails(BMW, new BigDecimal("3")));
CarDetails.add(new Receipt(BENZ, new BigDecimal("5")));
CarDetails Class:
class CarDetails {
myEnumClass carCompany;
BigDecimal amountOfCar;
I want to multiply yearOfFundation to numberOfCar for each company, so like:
for BMW=1916*3;
for BENZ= 1926*5;
and then plus them: (1916*3)(1926*5);
I want to use Stream() I think it might be possible, but the problem is when I use stream I get this Datatyp: Stram, which not Allows me to use: BigDecimal.multiply(BigDecimal).
any idea how can I write is correctly?
Thanks a lot!
Using stream and reduce, You could do something like this
BigDecimal res = numberOfcars
.stream()
.reduce(
BigDecimal.ZERO,
(BigDecimal acc, CarDetails c) -> acc.add(
c.getAmountOfCar().multiply(c.getCarCompany().getYearOfFoundation())
),
BigDecimal::add
);
Demo

Spring Boot validation takes float value in integer field

I'm trying to implement a POST service with request validation.
My Controller method looks something like below
public void updateScore(#Valid ScoreRequest)
ScoreRequest looks like below
import javax.validation.constraints.*;
import lombok.Data;
#Data
public class ScoreRequest {
#Min(0)
#Max(100)
#Digits(fraction = 0, integer = 3)
private Integer score;
...
}
It all works fine till I pass integer values for score, however If I pass fraction part as well, request goes through and Spring somehow truncates the fraction and uses the integer part in the request.
I was expecting it to throw a validation error since datatype of score doesn't match.
It works with followling request, and uses 10 as the score value in the request object. I'm expecting it to throw an error, what am I doing wrong?
{"score": 10.234234}
Spring Boot version: 2.0.3.RELEASE
I was trying to debug Spring Boot's validation classes to find what was happening, but after looking at the comment by #M.Denium I searched for Jackson issues and found a related SO entry.
Java Jackson - prevent float to int conversion when deserializing
I'm using answer by #Jichao Zhang, however Just to confirm answer by #Eduardo Sanchez-Ros works as well. This is what works for me.
ObjectMapper.configure(DESERIALIZATION_FEATURE.ACCEPT_FLOAT_AS_INT, false);
Don't use this annotation: #Digits(fraction = 0, integer = 3 with Integer since it is useless to set fractions for Integer.
Why don't you do:
#Min(0)
#Max(100)
#Digits(fraction = 0, integer = 3)
private BigDecimal score;
If you closely look at the definition of the #digits annotation,
#Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
So this annotation can be applied to methods also.
If you read the docs, it says this annotation can be applied to the following types
BigDecimal
BigInteger
CharSequence
byte (or Byte)
short (or Short)
int (or Integer)
long (or Long)
the integer field of the annotation checks for the number of integral digits while the fraction field of the annotation checks for the number of fractional digits.
Since, you declared your field to be an Integer value. It casts the value to an integer and truncates the fractional part.
This does not fail validations as both the fields satisfy the validation.
This annotation is ideally to be only used with BigDecimal type.

Quickly testing freemarker expressions

Today I was faced with the prospect of writing quite a few freemarker expressions. While the overall difficulty is not high, some of them will contain quite a few builtin calls (i.e. parsing formatted string to number, increasing it and formatting again).
That got me to thinking - how can I test that for development purpuses only to minimize the time spent? I know there are IDE tools that help with the syntax - however, what about testing the functionality I wrote on sample strings? Something that would allow me to parse ${" b lah"?trim} and check whether the output is what I expect? Running my app is obviously a possibility, but in my case it takes way too long to get to the part where using freemarker happens.
I would use a simple JUnit test to test that.
Example:
public class FreemarkerSandbox {
#Test
public void testFreemarker() throws TemplateException, IOException {
Configuration cfg = new Configuration();
Template template = cfg.getTemplate("trim.ftl", CharEncoding.UTF_8);
HashMap<String, Object> model = new HashMap<String, Object>();
Writer out = new StringWriter();
template.process(model, out);
assertEquals("b lah", out.toString());
}
}
With trim.ftl just containing the expression to test.
${" b lah"?trim}
It can be improved by passing the test cases in the model.

Spring Batch Passing list of values as a parameter

I want to pass list of id's as one of parameter to Spring batch. Is this possible to achieve?
Thanks in advance.
What you are trying to do is not possible.
From the JobParameter doc:
Domain representation of a parameter to a batch job. Only the
following types can be parameters: String, Long, Date, and Double. The
identifying flag is used to indicate if the parameter is to be used as
part of the identification of a job instance.
You might be tempted write your list of of id's to a comma delimited string and pass that as a single parameter but beware that when stored in the DB it has a length of at most 250 bytes. You'll either have to increase that limit or use another way.
Perhaps you can explain what why you need to pass that list of ids.
If you want to pass the list from ItemReader, then you have to get JobParameters first (you have to declare your reader to be step scoped for that, see this thread also).
You will have to put your list as a parameter to the JobParameters. As JobParameters is immutable, you will have to create a new object then
List yourList = ....
JobParameters jp = (JobParameters) fac.getBean("params");
Map map=params.getParameters();
map.put("yourList", list);
params=new JobParameters(map);
launcher.run(job, params);
You cannot use the List<T> concept itself in spring-batch, but I think you can implement your intentions(listOf(a, b, c, d..)) in the following way.
The job parameter itself receives a comma-separated string of items.
#Nonnull
private List<String> someList = Collections.emptyList();
#Value("#{jobParameters['someList']}")
public void setTableNames(#Nullable final String someList) {
if (StringUtils.isNotBlank(tableNames)) {
this.someList = Arrays.stream(StringUtils.split(someList, ","))
.map(String::trim)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList());
}
}
Hope it was helpful for using list-type parameters in spring-batch!
Thanks.

Accessing public static final field using JoSQL

I've been using JoSQL for quite a few months now and today I came across a problem I am not sure how to solve. I probably could solve it by binding variables/placeholders, but I'd like to include the fields in the query.
SELECT * FROM ...MyObject WHERE getType != com.mypackage.myclass.TYPE_A
This is the query that I have. TYPE_A is a public static final int attribute in "myclass" class. Accessing methods (such as getType) is easy, because getType is expected to be a method from MyObject - just that I do not write round brackets after it (this is how JoSQL works as far as I know).
Does anyone happen to have an idea how to access a public static final field?
JoSQL uses gentlyweb-utils; it seems to be some sort of Accessor/Getter/Setter framework. I'd love to access that attribute without having to bind variables, but I haven't been able to do so.
Thanks for your help in advance! I really appreciate it.
I think I have figured something out. First: it seems not possible to access the static variables for whatever reason. I've used the following approach to solve my issue:
create a method, which picks up a given JoSQL-statement
mark the constants, which you want to replace, by say "{?FULL_PACKAGE_AND$CONSTANT}"
use reflections to determine the column as well as the column (and value) from the field
iteratively replace the statement until no "{?"-values are available
Example:
JoSQL-statement looks like this:
(isWeapon = TRUE AND getItem.getType2 = {?com.l2jserver.gameserver.model.items.L2Item$TYPE2_WEAPON})
Method using the query-object:
final Query query = DataLayer.createJoSqlQuery(joSql);
Method (pre)processing the JoSQL-statement:
final Query query = new Query();
int variableColumn = 0;
while (joSql.indexOf("{?") > -1) {
variableColumn++;
final int startIndex = joSql.indexOf("{?");
final int endIndex = joSql.indexOf("}", startIndex);
final String value = joSql.substring(startIndex + 2, endIndex);
try {
final Object variableValue = Class.forName(value.split("\\$")[0]).getField(value.split("\\$")[1]).get(null);
query.setVariable(variableColumn, variableValue);
joSql = joSql.replace("{?" + value + "}", "?");
}
catch (...) {
e.printStackTrace();
}
}
query.parse(joSql);
return query;
The JoSQL-statement preprocessing method bascially iterates through a given JoSQL-statement and sees whether it contains the string "{?". If it does, it does some copy and paste (note the dollar-symbol right in front of the constant name).
Finally it creates the objects and sets them using something similar to prepared statements "setObject"-method. In the end it just replaces the values within the JoSQL-statement with question marks ("?") and sets a corresponding object in the newly created Query-object, which is later used to retrieve information.

Resources