Hi i have a race condition in given method i have 2 instances in kubernates and checking in redis
public void method(GuestDTO guestDTO) {
String executeName = "addingGuestToCache" + guestDTO.getUser();
if (!redisService.checkExecute(executeName)) {
redisService.startExecute(executeName);
OpenGuestDTO openGuestDTO = new OpenGuestDTO();
RMap<String, List<OpenGuestDTO>> openGuestDTOList = redisService.getOpenGuestDTOList();
List<OpenGuestDTO> userGuestList = openGuestDTOList.get(guestDTO.getUser());
if (userGuestList == null) {
userGuestList = Collections.synchronizedList(new ArrayList<OpenGuestDTO>());
}
for (OpenGuestDTO guestDTO1 : userGuestList) {
if (guestDTO1.getGuestName().equalsIgnoreCase(guestDTO.getGuestName())) {
redisService.deleteExecute(executeName);
return;
}
}
openGuestDTOList.add(openGuestDTO);
openGuestDTOList.fastPut(guestDTO.getUser(), userGuestList);
redisService.deleteExecute(executeName);
}else{
method(guestDTO);
}
}
i am trying to change my api from last.fm to deezer and it has been a hurdle for me. please help. below is my code and endpoints.
LAST.fm endpoint : http://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key=c3bbdcbc61af20f159e92612a56c4122&artist=ynw%20melly&track=suicidal&format=json
Deezer endpoint : http://api.deezer.com/search?q=Alan%20Walker%20-%20Darkside
JAVA CODE
static String parsingImageSong(String data) {
if (!TextUtils.isEmpty(data)) {
try {
JSONObject mJsonObject = new JSONObject(data);
if (mJsonObject.opt("track") != null) {
JSONObject mJsTracks = mJsonObject.getJSONObject("track");
if (mJsTracks.opt("album") != null) {
JSONObject mJsAlbum = mJsTracks.getJSONObject("album");
if (mJsAlbum.opt("image") != null) {
JSONArray mJsImgs = mJsAlbum.getJSONArray("image");
if (mJsImgs.length() > 0) {
for (int j = 0; j < mJsImgs.length(); j++) {
JSONObject mJsImg = mJsImgs.getJSONObject(j);
String sizeImg = mJsImg.getString("size");
if (sizeImg.equalsIgnoreCase("extralarge")) {
return mJsImg.getString("#text").replace("300x300","3000x3000");
}
}
}
}
}
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
return null;
}
}
env:
jdk: 17.0.1
mapstruct: 1.5.1.Final
Using the default configuration I generated the following code
protected AgentInfo wealthProdAccountInfoDTOToAgentInfo(WealthProdAccountInfoDTO wealthProdAccountInfoDTO) {
if ( wealthProdAccountInfoDTO == null ) {
return null;
}
String agentName = null;
String agentIdentityType = null;
String agentIdentityNo = null;
String agentIdentityExpireAt = null;
agentName = wealthProdAccountInfoDTO.getAgentName();
agentIdentityType = wealthProdAccountInfoDTO.getAgentIdentityType();
agentIdentityNo = wealthProdAccountInfoDTO.getAgentIdentityNo();
agentIdentityExpireAt = wealthProdAccountInfoDTO.getAgentIdentityExpireAt();
AgentInfo agentInfo = new AgentInfo( agentName, agentIdentityType, agentIdentityNo, agentIdentityExpireAt );
return agentInfo;
}
But I want to return null when all field of source are null, like this
protected AgentInfo wealthProdAccountInfoDTOToAgentInfo(WealthProdAccountInfoDTO wealthProdAccountInfoDTO) {
if ( wealthProdAccountInfoDTO == null ) {
return null;
}
// add check logic
if (agentName == null && agentIdentityType == null && agentIdentityNo == null && agentIdentityExpireAt == null) {
return null;
}
String agentName = null;
String agentIdentityType = null;
String agentIdentityNo = null;
String agentIdentityExpireAt = null;
agentName = wealthProdAccountInfoDTO.getAgentName();
agentIdentityType = wealthProdAccountInfoDTO.getAgentIdentityType();
agentIdentityNo = wealthProdAccountInfoDTO.getAgentIdentityNo();
agentIdentityExpireAt = wealthProdAccountInfoDTO.getAgentIdentityExpireAt();
AgentInfo agentInfo = new AgentInfo( agentName, agentIdentityType, agentIdentityNo, agentIdentityExpireAt );
return agentInfo;
}
how should I configure it?
Unfortunately there's no clean solution for your problem, except implementing code for null check by yourself, Marc specified the right approach to your problem (I'd go with it personally or would use default method for the same purpose).
I can add some workarounds, which will only work if mapping target is inner object:
Use #BeforeMapping to set input inner object to null, so when there will be null-check it will be skipped
#BeforeMapping
default void clearData(TestB source, #MappingTarget TestA target) {
TestD innerD = source.getInnerD();
if (innerD.getSecond() == null && innerD.getFirst() == null) {
source.setInnerD(null);
}
}
And it will generate the following code:
#Override
public TestA from(TestB input) {
....
clearData( input, testA ); //set input field to null
testA.setInnerC( fromInner( input.getInnerD() ) );
....
}
#Override
public TestC fromInner(TestD input) {
if ( input == null ) { //skip because of null
return null;
}
....
}
Use #AfterMapper to set output parameter to null(it will be mapped in the first place, so there will be some overhead)
#AfterMapping
default void clearData(TestB source, #MappingTarget TestA target) {
TestD innerD = source.getInnerD();
if (innerD.getSecond() == null && innerD.getFirst() == null) {
target.setInnerC(null);
}
}
And generated code will be:
#Override
public TestA from(TestB input) {
....
testA.setInnerC( fromInner( input.getInnerD() ) ); //field is actually mapped but cleared later
clearData( input, testA );
return testA;
}
As I said, these solutions aren't really clean and should be seen as workarounds only. Pros of these workaround is that you will keep working with autogenerated code and these hacks will be hidden inside that code.
UPD Stumbled upon #DecoratedWith lately and it also can do the trick. https://mapstruct.org/documentation/stable/reference/html/#_customizing_mappings
Just implement decorator for iterable2iterable mapping method: List<A> from(List<b> b) and just manually iterate over b checking if all b's fields are null and if so skip it
brute force... it's a simple class, so create a custom mapper
#Mapper
public interface AgentInfoMapper {
#Named("AgentInfoNullIfContentsNull")
public static AgentInfo custom(WealthProdAccountInfoDTO dto) {
if ( wealthProdAccountInfoDTO == null ) {
return null;
}
if (agentName == null && agentIdentityType == null && agentIdentityNo == null && agentIdentityExpireAt == null) {
return null;
}
// mapping code
}
}
https://www.baeldung.com/mapstruct-custom-mapper
Thanks to ArtemAgaev's idea, I ended up considering using #AfterMapping and java reflection for this type of scenario
#AfterMapping
default void cleanData(#MappingTarget AccountInfoDomain domain) {
Optional.ofNullable(domain).ifPresent(c -> {
if (isAllFieldNull(domain.getAgentInfo())) {
domain.setAgentInfo(null);
}
});
}
public static boolean isAllFieldNull(Object o) {
Object[] fieldsValue = getFieldsValue(o);
return Optional.ofNullable(fieldsValue).map(f -> Arrays.stream(f).allMatch(Objects::isNull)).orElse(true);
}
public static Object[] getFieldsValue(Object obj) {
if (null != obj) {
final Field[] fields = getFields(obj instanceof Class ? (Class<?>) obj : obj.getClass());
if (null != fields) {
final Object[] values = new Object[fields.length];
for (int i = 0; i < fields.length; i++) {
values[i] = getFieldValue(obj, fields[i]);
}
return values;
}
}
return null;
}
I'm telling you that I was able to get the highs with and without inheritance automated, but now I have the same problem to edit, it happens
I want to first edit the methods of the superclass and then the superclass
But I do not succeed:
ParamBuilder.java
private LinkedList<Object>loadMethods(IPersistente ip) throws Exception{
LinkedList<Method> m = new LinkedList();
Child s = ip.getClass().getAnnotation(Child.class);
Method[] me = null;
if(s != null && ip.getId() == 0){
me = ip.getClass().getSuperclass().getDeclaredMethods();
} else {
// only this if is left so that the modifications with inheritances are automated, xq with the highs I could
if(s != null){
me = ip.getClass().getSuperclass().getDeclaredMethods();
} else {
me = ip.getClass().getDeclaredMethods();
}
}
for(Method campo : me){
if (campo.getName().startsWith("get") && !campo.getName().startsWith("getClass")) {
Method metodo = campo;
if(metodo.getParameterCount() == 0) {
if(metodo.isAnnotationPresent(Sort.class)){
m.add(metodo);
}
}
}
}
if(ip instanceof IDependiente && !ip.check()){
Collections.sort(m, new SortDesc());
} else {
Collections.sort(m, new SortAsc());
}
return load(ip, m);
}
I await your responses and greetings.
I have a requirement where I need to make few Java calls and retrieve necessary values. These are all strings. I need to write this to a console with comma separated values. Like below:
3,Till,,Till,Weiss,,
3,ugilad,,ugilad,ugilad,,
3,admintest,,admin,test,abc#sample.com,
Expected should be:
userid,firstname,lastname,email
3,Till,,Till,Weiss,,
3,ugilad,,ugilad,ugilad,,
3,admintest,,admin,test,abc#sample.com,
Now I need to add columns to these values. Say: userId, firstName, lastName like this. How can I achieve this dynamically using Java code? Here is the code that I wrote:
if (usersList.totalCount != 0 && usersList.totalCount >= 1) {
System.out.println("usersList.totalCount ----->"
+ usersList.totalCount);
for (KalturaUser user : usersList.objects) {
if (user != null) {
if (user.id != null) {
String userRole = getUserRole(user.id);
String cnum = getUserUniqueId(user.email);
// if (userRole != null) {
// if (userRole.equals("adminRole")
// || userRole
// .equals("privateOnlyRole")) {
// sb1.append(action);
if (user.id != null) {
sb.append(user.id);
} else {
sb.append(",");
}
String action = "1";
if (cnum != null) {
if (userRole == null) {
action = "3";
}
} else {
action = "3";
}
if (action != null) {
sb1.append(action);
}
if (cnum != null) {
sb1.append(",").append(cnum);
} else {
sb1.append(",").append(user.id);
sb1.append(",");
}
if (user.firstName != null) {
sb.append(",").append(user.firstName);
sb1.append(",").append(user.firstName);
} else {
sb.append(",");
sb1.append(",");
}
if (user.lastName != null) {
sb.append(",").append(user.lastName);
sb1.append(",").append(user.lastName);
} else {
sb.append(",");
sb1.append(",");
}
if (userRole != null) {
sb.append(",").append(userRole);
// sb1.append(",").append(userRole);
} else {
sb.append(",");
// action = "3";
// sb1.append(action);
}
// sb1.append("1");
if (user.email != null) {
sb.append(",").append(user.email);
sb1.append(",").append(user.email);
} else {
sb.append(",");
sb1.append(",");
}
if (userRole != null) {
sb1.append(",").append(userRole);
} else {
sb1.append(",");
}
// sb1.append("1");
if (user.partnerData != null) {
if (user.partnerData.startsWith("pw")
&& user.partnerData.length() == 43) {
sb.append(",");
}
if (user.partnerData.length() > 43) {
String partnerData = user.partnerData
.substring(44);
sb.append(",").append(partnerData);
}
if (!user.partnerData.startsWith("pw")) {
sb.append(",").append(user.partnerData);
}
}
sb.append(System.getProperty("line.separator"));
sb1.append(System.getProperty("line.separator"));
}
}
}
}
// System.out.println(sb);
System.out.println(sb1);
As per your code you are appending everything to a string buffer(sb) and printing it at once. So in between the loop you could create a string header and assign value based on condition. And outside the loop first print header and then print the buffer. That would be the simplest soultion. However if the amount of data is buge it would be better to use a file. Write everything to a file, construct the header and then after the loop print the header and then print the file. A sample with dummy logic and classes
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
class UserList {
public int totalCount;
public List<KalturaUser> objects;
public UserList(List<KalturaUser> objects) {
this.objects = objects;
this.totalCount = (objects != null) ? objects.size() : 0;
}
}
class KalturaUser {
public String id;
public String email;
public String firstName;
public String lastName;
public String partnerData;
public KalturaUser(String id, String email, String firstName,
String lastName, String partnerData) {
this.id = id;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
this.partnerData = partnerData;
}
}
public class DynamicHeader {
private static final String NEW_LINE = System.getProperty("line.separator");
public static void main(String[] args) throws Exception {
UserList usersList = init();
RandomAccessFile csv = new RandomAccessFile("temp.csv","rw");
csv.setLength(0); //Clears the file
String header = "";
if (usersList.totalCount >= 1) {
for (KalturaUser user : usersList.objects) {
if (user != null && user.id != null) {
List<String> row = new ArrayList<String>();
String userRole = getUserRole(user.id);
String cnum = getUserUniqueId(user.email);
row.add(getNullSafeValue(user.id));
String action = "1";
if (cnum == null || userRole == null) {
action = "3";
}
row.add(action);
if (cnum != null) {
row.add(cnum);
header = "uniqueid,firstname,lastname,email";
} else {
row.add(user.id);
header = "userid,firstname,lastname,email";
}
row.add(getNullSafeValue(user.firstName));
row.add(getNullSafeValue(user.lastName));
row.add(getNullSafeValue(userRole));
row.add(getNullSafeValue(user.email));
if (user.partnerData != null) {
if (user.partnerData.startsWith("pw")) {
if (user.partnerData.length() == 43) {
row.add("");
} else if (user.partnerData.length() > 43) {
row.add(user.partnerData.substring(44));
}
} else {
row.add(user.partnerData);
}
}
csv.write(row.toString().replace("[", "").replace("]", "").replace(", ", ",").getBytes());
csv.write(NEW_LINE.getBytes());
}
}
}
csv.seek(0);
System.out.println(header);
String data;
while((data = csv.readLine()) != null){
System.out.println(data);
}
csv.close();
}
private static UserList init() {
List<KalturaUser> userObjs = new ArrayList<KalturaUser>();
userObjs.add(new KalturaUser("1", null, "Till", "Till", "Weiss"));
userObjs.add(new KalturaUser("2", null, "ugilad", "ugilad", "ugilad"));
userObjs.add(new KalturaUser("3", "abc#sample.com", "admin", "test", "admintest"));
return new UserList(userObjs);
}
private static String getNullSafeValue(String str) {
return (str != null) ? str : "";
}
private static String getUserUniqueId(String email) {
return (email != null) ? email.substring(0, email.indexOf("#")) : null; //Replace with proper logic
}
private static String getUserRole(String id) {
return ("2".equals(id)) ? "Role 2" : null; //Replace with proper logic
}
}
Apart from this you could do some clean ups in your code like below. Also insteaded of constructing string you could just add it to a list. The toString of list gives you a comma separated value.
(usersList.totalCount != 0 && usersList.totalCount >= 1)
could be reduced to (usersList.totalCount > 0)
if (user != null) {
if (user.id != null) {}
}
If you dont have to do anything specific when (user != null) then, this could be combined to
if (user != null && user.id != null) {}
And
if (cnum != null) {
if (userRole == null) {
action = "3";
}
} else {
action = "3";
}
This could be reduced to
if (cnum == null || userRole == null) {
action = "3";
}