Consider this method signature that I have
#Cacheable(
key="#name+'::'+#age+'::'+#country"
)
public User validate(String name, String age, String country) {
...
}
Notice the key that I have. Currently I am able to concatenate the name, age and country variables. But on top of concatenating them, I also want to convert the entire expression into a lowercase value.
For example if someone called this method like so: validate("John","24","USA"),
then I want my key to be resolved as: john::24::usa. Notice all the uppercase letters have become lowercase.
TLDR; how to write a spel expression which concatenates multiple variables and converts the entire result into lowercase?
Expression exp = new SpelExpressionParser()
.parseExpression("(#foo + '::' + #bar).toLowerCase()");
StandardEvaluationContext ctx = new StandardEvaluationContext();
ctx.setVariable("foo", "XXX");
ctx.setVariable("bar", "YYY");
System.out.println(exp.getValue(ctx));
xxx::yyy
Related
#RequestMapping(value = "/{userId:\\d+}", method = RequestMethod.DELETE)
public void delete(#PathVariable Long userId) {
try{
this.authorService.delete(userId);
}catch(Exception e){
throw new RuntimeException("delete error");
}
}
Anybody know what url should I match for this definition "/{userId:\d+}", could you give me an example, like "/userid=1", is this right?
I guess that definition like this "/{userId:\d+}" , using regular expression in url to make sure it pass a number parameter.I am not sure about that , if anybody knows it please give me a link for further learning, thank you!
No, that expression maps /1 for example, all the digits.
The syntax {varName:regex} declares a URI variable with a regular expressions with the syntax {varName:regex} — e.g. given URL "/spring-web-3.0.5 .jar", the below method extracts the name, version, and file extension:
#GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(#PathVariable String version, #PathVariable String ext) {
// ...
}
Check the complete doc here
It will match any digit. For example,
/1, /11, /123.
/{userId:\\d+} ===> map one or more digits after / to variable userId.
Regular expression for one or more digits is \d+, but since you are using it as a string you need to escape it using another \.
I am replacing dynamic parameter using dynamic values of any string.
I have used below code :
public static String setDynamicParameter(String text,Object[] values){
MessageFormat messageFormat = new MessageFormat(text);
return messageFormat.format(values);
}
public static void main(String [] args) {
String text = "Test message 'test'";
System.out.println(setDynamicParameter(text, null));
}
In the above code I am not using any dynamic parameter for test purpose.
OUTPUT : Test message test
What I am facing problem : It replace the single quot.
why it replaced single quot?
This is from the MessageFormat documentation:
Within a String, a pair of single quotes can be used to quote any arbitrary characters except single quotes. For example, pattern string "'{0}'" represents string "{0}", not a FormatElement. A single quote itself must be represented by doubled single quotes '' throughout a String.
I am trying to create a jooq query string the following way
DSL.using(SQLDialect.MYSQL)
.select(
ImmutableList.of(DSL.field("Name"))
.from(DSL.table("Account"))
.where(DSL.field("Name").eq("Yaswanth's Company"))).toString()
The resultant query string has the single quote escaped with another single quote which is the default mySQL way of escaping single quotes.
"select Name from Account where Name = 'Yaswanth''s Company'"
But I would need the single quote to be escaped with backslash as I am forming the query string for salesforce. (which is called SOQL).
I need the query string this way
"select Name from Account where Name = 'Yaswanth\\'s Company'"
I have looked at the jooq library code and this is hardcoded in the DefaultBinding class
private final String escape(Object val, Context<?> context) {
String result = val.toString();
if (needsBackslashEscaping(context.configuration()))
result = result.replace("\\", "\\\\");
return result.replace("'", "''");
}
Is there a way for me to override this default behavior via configuration or settings which can be passed by DSL.using(*, *)?
Most SQL databases follow the SQL standard of doubling the single quote for escaping, but it certainly makes sense to make this functionality configurable. We'll probably do this for jOOQ 3.10 with #5873.
In the meantime, the best workaround for you is to write your own data type binding for all String types and override the DefaultBinding behaviour when generating the SQL string. Something along the lines of this:
Code generation configuration
Using <forcedTypes/>
<forcedType>
<userType>java.lang.String</userType>
<binding>com.example.AlternativeEscapingStringBinding</binding>
<!-- add other vendor-specific string type names here -->
<types>(?i:N?(VAR)?CHAR|TEXT|N?CLOB)</types>
</forcedType>
Data type binding
public class AlternativeEscapingStringBinding implements Binding<String, String> {
...
#Override
public void sql(BindingSQLContext<String> ctx) throws SQLException {
if (ctx.paramType() == ParamType.INLINED)
if (ctx.value() == null)
ctx.render().sql('null');
else
ctx.render()
.sql('\'')
.sql(ctx.value().replace("'", "\\'"))
.sql('\'');
else
ctx.render().sql('?');
}
}
If you're not using the code generator
You can still apply your own data type bindings manually to your fields as such:
DSL.field("Name", SQLDataType.VARCHAR
.asConvertedDataType(new AlternativeEscapingStringBinding()));
You'll just have to remember this every time...
Password must contains :
1 Upper letter
1 lower letter
1 digit
1 special symbol
Minimum 8 symbols
Here it is my regex:
^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#_$%^&*-]).{8,}$
But when i try to validate for example with password: Test_123 it returns me false
here is my code :
public class PasswordCheck {
static Logger logger = Logger.getLogger(CommonHelper.class);
private static final String PASSWORD_PATTERN = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#_$%^&*-]).{8,}$";
private Pattern pattern;
private Matcher matcher;
public PasswordCheck() {
pattern = Pattern.compile(PASSWORD_PATTERN);
}
/**
* Validate password with regular expression
*
* #param password
* password for validation
* #return true valid password, false invalid password
*/
public boolean validate(final String password) {
matcher = pattern.matcher(password);
System.out.println(password);
System.out.println(matcher.matches());
return matcher.matches();
}
}
I just try it to set new String in validate function with the same text: Test_1523 and return me true but when i post this string via rest service and pass it to the function returns me false
No matter if you are using regular expressions or other means to validate those strings - but please: don't push everything into one piece of code or regex.
You want to create code that is easy to read and maintain; and a single regex containing so much "coded" knowledge wont help with that. I have more than once used something like
interface PasswordValidator {
boolean isValid(String input);
String getErrorMessage();
}
To then create various classes implementing such an interface. And finally, you simply create one object per implementation class; and you can put those into some static list. And then validating means: just run all validator objects in that list. On fail, you can directly ask for the error message for the user (so you can tell him exactly what is missing; instead of throwing the whole rule set at him again).
Not saying that something like that is always required, but in my experience: password rules might change frequently. Hard-baking them into regexes is rarely a durable approach.
I'm looking for a tool which will allow me use command-line-style (preferably POSIX) strings to initialize an object' properties and attributes.
For example, you'd provide it with String input formatted like so:
String input = "--firstName=John --MiddleName=\"Louis Victor\" --lastName=Smith";
... and it would setFirstName("John"), setMiddleName("Louis Victor") and setLastName("Smith") on a given object. (which could be a JavaBean)
Please note that the input is a single String, not an array String[] as is the case with many popular CLI argument "parsers".
This is all similar to args4j but I couldn't get that to work... and I'm hoping to avoid using #annotations.
Does anyone have code/libraries/tools which could accomplish this?
For your use case, forget regular CLI parsers, you need a custom-tailored solution. If you really have such a simple argument syntax (parameters always begin with --, no occurrences of -- in the parameter values), you can use a simple Guava-based solution like this class:
Parse the String Arguments
public class ArgParser{
// split on (optional whitespace) + "--"
private final Splitter paramSplitter = Splitter.on(
Pattern.compile("\\s*\\-{2}")).omitEmptyStrings();
// find key=value (with optional double quotes around value)
private final Pattern keyValuePattern = Pattern
.compile("(.+?)=\"?(.*?)\"?$");
public Map<String, String> getParamValues(final String posixString){
final Map<String, String> paramValues = Maps.newLinkedHashMap();
Matcher matcher;
for(final String param : paramSplitter.split(posixString)){
matcher = keyValuePattern.matcher(param);
if(!matcher.find()){
throw new IllegalArgumentException("Bad parameter: " + param);
}
paramValues.put(matcher.group(1), matcher.group(2));
}
return paramValues;
}
}
Usage
final String input =
"--firstName=John --middleName=\"Louis Victor\" --lastName=Smith";
System.out.println(new ArgParser().getParamValues(input));
Output
{firstName=John, middleName=Louis Victor, lastName=Smith}
Now you can take the map and use it with a Bean library like commons-beanutils (I prefer the Spring BeanWrapper personally, but that only makes sense if you use Spring anyway)
Define the Bean Class
Any way, I'll use this value holder class:
public class Name{
private String firstName;
private String middleName;
private String lastName;
#Override
public String toString(){
return Objects
.toStringHelper(this)
.add("first name", firstName)
.add("middle name", middleName)
.add("last name", lastName)
.toString();
}
// + getters & setters
}
Set the Bean Properties
Now we'll use BeanUtils.populate(Object, Map) to apply the parameter values, like this:
final String input =
"--firstName=John --middleName=\"Louis Victor\" --lastName=Smith";
final Map<String, String> paramValues =
new ArgParser().getParamValues(input);
final Name name = new Name();
BeanUtils.populate(name, paramValues);
System.out.println(name);
Output:
Name{first name=John, middle name=Louis Victor, last name=Smith}
Caveat: Supported Property Types
BeanUtils.populate() supports setting the following property types:
... String, boolean, int, long, float, and double.
In addition, array setters for these
types (or the corresponding primitive
types) can also be identified.
Source: BeanUtilsBean.populate(Object, Map)
If you need parameter conversion beyond that, you should probably look into using the Spring BeanWrapper after all, it's extremely powerful, has many built-in property editors and you can add custom property editors. Just change the code like this:
final Name name = new Name();
final BeanWrapper wrapper = new BeanWrapperImpl(name);
wrapper.setPropertyValues(paramValues);
Reference:
BeanWrapper
PropertyAccessor.setPropertyValues(Map)
If I understand correctly, you are looking for a Java library to parse POSIX-style command line parameters. I used JSAP some time ago and it was really cool (it was using XML configuration back then).
This
-firstName John -lastName Smith
is no POSIX, you mean
--firstName John --lastName Smith
This may be the reason, why you can't get it working.
Update:
As I look at the example, it doesn't look like it could be the reason.