How to read properties with special characters from application.yml in springboot - java

application.yml
mobile-type:
mobile-codes:
BlackBerry: BBSS
Samsung: SAMS
Samsung+Vodafone: SAMSVV
While reading (Samsung+Vodafone)key from application yml file , we are getting.
concatenated String format as 'SamsungVodafone' .
Morever we heve tried "Samsung'/+'Vodafone": SAMSVV but the result was same and we have tried other symbol such as '-' so its working fine .
For reading key and value from application yml file . we have written below code.
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
#ConfigurationProperties(prefix = "mobile-type")
#Component
public class mobileTypeConfig {
Map<String, String> mobileCodes;
public Map<String, String> getMobileCodes() {
return mobileCodes;
}
public void setMobileCodes(Map<String, String> mobileCodes) {
this.mobileCodes= mobileCodes;
}
}
Note :Spring Boot Version
2.0.6.RELEASE

Use square brackets not to escape any character and encode that in double quotes
mobile-type:
mobile-codes:
BlackBerry: BBSS
Samsung: SAMS
"[Samsung+Vodafone]": SAMSVV
Output
{BlackBerry=BBSS, Samsung=SAMS, Samsung+Vodafone=SAMSVV}
Binding
When binding to Map properties, if the key contains anything other than lowercase alpha-numeric characters or -, you need to use the bracket notation so that the original value is preserved. If the key is not surrounded by [], any characters that are not alpha-numeric or - are removed. For example, consider binding the following properties to a Map:
acme:
map:
"[/key1]": value1
"[/key2]": value2

please keep in mind that the left side is a yml key, not an arbitrary string. my suggestion or your usecase would be to have a map with both on the right side such as:
foo:
- name: "Samsung+Vodafone"
code: "SAMSVV"
- name: "BlackBerry"
code: "BBMS"
- name: "Samsung"
codes:
- "SAMS"
- "SMG"
you will have to change your class structure slightly, but you could actually reconstruct your initial approach from that.

Related

Swagger Client Codegenerator from yaml file adds an underscore to String values of enums

When I try code generator for a swagger yaml file sent to me by a consuming API I get underscores in the generated classes. I wonder why that is? Can someone explain me why this happens and how to avoid it?
BodyType:
type: string
enum:
- 0
- 1
- 2
- 3
The resulting enum created in Java looks as follows:
public enum BodyTypeEnum {
_0("0"),
_1("1"),
_2("2"),
_3("3");
If I change in the yaml from String to Integer it looks like this:
#JsonAdapter(BodyTypeEnum.Adapter.class)
public enum BodyTypeEnum {
NUMBER_0(0),
NUMBER_1(1),
NUMBER_2(2),
NUMBER_3(3);

Deploy Quarkus Microservice with RestClient

Anyone knows how to replace the character "/" in application.yaml in Quarkus
# REST Client configuration property
org:
acme:
restclient:
CountriesService/mp-rest/url: https://restcountries.eu/rest
When I deploy, this error seems to appear
Error: release insurance-svc failed, and has been uninstalled due to atomic being set: ConfigMap "insurance-svc-dev-config" is invalid: [data[coreClient/mp-rest/url]: Invalid value: "coreClient/mp-rest/url": a valid config key must consist of alphanumeric characters, '-', '_' or '.' (e.g. 'key.name', or 'KEY_NAME', or 'key-name', regex used for validation is '[-._a-zA-Z0-9]+'), data[identityClient/mp-rest/scope]: Invalid value: "identityClient/mp-rest/scope": a valid config key must consist of alphanumeric characters, '-', '_' or '.' (e.g. 'key.name', or 'KEY_NAME', or 'key-name', regex used for validation is '[-._a-zA-Z0-9]+'), data[coreClient/mp-rest/scope]: Invalid value: "coreClient/mp-rest/scope": a valid config key must consist of alphanumeric characters, '-', '_' or '.' (e.g. 'key.name', or 'KEY_NAME', or 'key-name', regex used for validation is '[-._a-zA-Z0-9]+'), data[identityClient/mp-rest/url]: Invalid value: "identityClient/mp-rest/url": a valid config key must consist of alphanumeric characters, '-', '_' or '.' (e.g. 'key.name', or 'KEY_NAME', or 'key-name', regex used for validation is '[-._a-zA-Z0-9]+')
Is there any way to change the way it configs without adding whole baseUri into annotation #RegisterRestClient()?
You can use different approach, you can create a custom configuration property to hold the URI. Then create a Factory that reads or has injected this configuration property and is used to instantiate your rest client.
URL apiUrl = new URL("http://localhost:9080/onlineMusicService");
MusicPlaylistService playlistSvc =
RestClientBuilder.newBuilder()
.baseUrl(apiUrl)
.register(PlaylistResponseExceptionMapper.class)
.build(MusicPlaylistService.class);
List<String> playlistNames = playlistSvc.getPlaylistNames();
for (String name : playlistNames) {
List<Song> songs = playlistSvc.getPlaylist(name);
if (hasSongBy(songs, "band name")) {
coolPlaylists.add(name);
}
}
You can read that url from the custom configuration property with the name you want.
I'd recommend watching this pull request: https://github.com/quarkusio/quarkus/pull/17220
Once it is merged and a Quarkus version with it released, you'll be able to use quarkus.rest-client."org.acme.restclient.CountriesService".url=https://restcountries.eu/rest instead - the key does not contain a slash, so it's compatible with Kubernetes

Why won't my Java Map compile in IntelliJ?

I'm trying to create a Scrabble game using Java in IntelliJ. I decided to use a Map<Character, Integer> which will contain each letter tile and its corresponding scoring value. I figured I could use the ofEntries shorthand to initialize the values of the Map but each time I try to compile my program I get an error.
error: cannot find symbol Map.entry('A',1)
symbol: method entry(char,int)
location: interface Map
26 errors (1 for each Map entry)
At first I thought it might have something to do with the Map being of type Character, Integer and the error mentioning entry(char,int) but it is my understanding that Java uses autoboxing between primitives and their object wrappers.
import java.util.Map;
class Scrabble {
private final Map<Character, Integer> LETTER_SCORES = Map.ofEntries(
Map.entry('A',1), Map.entry('E',1), Map.entry('I',1), Map.entry('O',1),
Map.entry('U',1), Map.entry('L',1), Map.entry('N',1), Map.entry('R',1),
Map.entry('S',1), Map.entry('T',1), Map.entry('D',2), Map.entry('G',2),
Map.entry('B',3), Map.entry('C',3), Map.entry('M',3), Map.entry('P',3),
Map.entry('F',4), Map.entry('H',4), Map.entry('V',4), Map.entry('W',4),
Map.entry('Y',4), Map.entry('K',5), Map.entry('J',8), Map.entry('X',8),
Map.entry('Q',10), Map.entry('Z',10)
);
private String word;
private int wordScore;
Scrabble(String word) {
this.word = word;
}
Please go to Project Structure | Project | Project SDK and define here JDK > 9 and Language level > 9. Also go to Project Structure | Modules and check that corresponding language level for module is defined here as well. Your code sample should compile without failures with JDK > 9 as was correctly mentioned in comments.

Swagger Error Expected type string but found type integer

I started working recently on swagger to generate documentation for our RESTful apis. I use the yamlbeans-1.09.jar to convert my Java DTOs to a yaml file.
Everything works fine and the yaml is even validated properly on the http://www.yamllint.com/ but still while testing it with the Swagger interface, it gives an error "Expected type string but found type integer" and "No enum match for: 2" wherever I mention the swagger : 2.0 in the file.
My sample yml file is:
basePath: /employment
host: api.xxxx.com
schemes:
- https
swagger: 2.0
info:
title: API Doc
description: Description for the info goes here
version: 1.0.0
It always tends to give an error just a line number before the swagger version. Any help will be appreciated.
Edit: I have defined the swagger version as string in the java code and written as described below:
HashMap<String, Object> rootElementsForYml = new HashMap<String, Object>();
rootElementsForYml.put(SWAGGER, "2.0");
rootElementsForYml.put(HOST, "api.xxxx.com");
rootElementsForYml.put(BASEPATH, basePath);
rootElementsForYml.put(SCHEMES, new String[]{"https"});
But still it gives no result and the same error.
That's because the version value is a string and not a number. Just specifying 2.0 is interpreted as a number. Wrap it with quotes like "2.0" and it would work fine.

A custom tokenizer for Java

I am developing an application in which I need to process text files containing emails. I need all the tokens from the text and the following is the definition of token:
Alphanumeric
Case-sensitive (case to be preserved)
'!' and '$' are to be considered as constituent characters. Ex: FREE!!, $50 are tokens
'.' (dot) and ',' comma are to be considered as constituent characters if they occur between numbers. For ex:
192.168.1.1, $24,500
are tokens.
and so on..
Please suggest me some open-source tokenizers for Java which are easy to customize to suit my needs. Will simply using StringTokenizer and regex be enough? I have to perform stopping also and that's why I was looking for an open source tokenizer which will also perform some extra things like stopping, stemming.
A few comments up front:
From StringTokenizer javadoc:
StringTokenizer is a legacy class that is retained for compatibility
reasons although its use is discouraged in new code. It is recommended
that anyone seeking this functionality use the split method of String
or the java.util.regex package instead.
Always use Google first - the first result as of now is JTopas. I did not use it, but it looks it could work for this
As for regex, it really depends on your requirements. Given the above, this might work:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Mkt {
public static void main(String[] args) {
Pattern p = Pattern.compile("([$\\d.,]+)|([\\w\\d!$]+)");
String str = "--- FREE!! $50 192.168.1.1 $24,500";
System.out.println("input: " + str);
Matcher m = p.matcher(str);
while(m.find()) {
System.out.println("token: " + m.group());
}
}
}
Here's a sample run:
$ javac Mkt.java && java Mkt
input: --- FREE!! $50 192.168.1.1 $24,500
token: FREE!!
token: $50
token: 192.168.1.1
token: $24,500
Now, you might need to tweak the regex, for example:
You gave $24,500 as an example. Should this work for $24,500abc or $24,500EUR?
You mentioned 192.168.1.1 should be included. Should it also include 192,168.1,1 (given . and , are to be included)?
and I guess there are other things to consider.
Hope this helps to get you started.

Categories

Resources