sinch instant message writable add extra field - sinch

Hi how to add extra field to the writable for passing additional content to the data map , for example i want to able to pass url for image thus allow image sharing , how to go about , am mostly js dev , so not really how to implement add new features to work sinch server
public final class WritableMessage {
private static final int HEADER_MAX_SIZE = 1024;
private final String messageId;
private String textBody;
private string extraContent;// added here for passing img url
private List<String> recipientIds;
private Map<String, String> headers;
private int headerSize;
public WritableMessage(String recipientUserId, String textBody, extraContent) {
this();
this.addExtra(extraContent); // but the sinch doesnt allow overide
this.addRecipient(recipientUserId);
this.setTextBody(textBody);
}

Use addHeader to add extra stuff to you message
public WritableMessage(String recipientUserId, String textBody, string imageUrl) {
this();
this.addHeader("imageUrl", imageUrl);
this.addRecipient(recipientUserId);
this.setTextBody(textBody);
}

Related

How to generate cache CustomKey for Redis in Spring Boot

I have spring boot application which is integrated with Redis cache. Have to implement caching for one of the method call. That method argument is an object with multiple params which is external Request object. This object params will vary for each request also based on that param and its values output of the method is varies. I need to create a cache key using that Request object field/param values. How to achieve it.
We can use SimpleKeyGenerator only when method params are static?
UserService.java
#Cacheable(value = "usercache", keyGenerator="customKeyGenerator")
public UserResponse getUserResp(User user){
//Some backend calls
return user
}
User.java
public class User {
private String firstname;
private String lastname;
private Integer age;
private Date dob;
private Address address;
// Another 10 params
}
In this method implementation User object is dynamic. I have to create a cache key based on User object fields which is having valid non null values. How to achieve it.
I have implemented as like below.
User.java
public class User implements Serializable {
private String firstname;
private String lastname;
private Integer age;
private Date dob;
private Address address;
// Another 10 params
#Override
public int hashCode() {
final int prime = 31;
//Add necessary fields
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
//Add necessary fields
}
}
public class UserKeyGenerator implements KeyGenerator{
private static final String UNDERSCORE_DELIMITER = "_";
#Override
public Object generate(Object target, Method method, Object... params) {
String cacheKey = null;
if(params.length > 0) {
StringJoiner paramStrJoiner = new StringJoiner(UNDERSCORE_DELIMITER);
User userReq = (User) params[0];
paramStrJoiner.add(target.getClass().getSimpleName());
paramStrJoiner.add(method.getName());
paramStrJoiner.add(String.valueOf(userReq.hashCode()));
cacheKey = paramStrJoiner.toString();
}
return cacheKey;
}

Why methods doesn't see values set in constructor? (Spring Boot)

I have a class AuthorizationService like this:
#Service
public class AuthorizationService {
private final String code;
private final String client_id;
private final String redirect_uri;
private final String scope;
private final String show_dialog;
#Autowired
public AuthorizationService(
#Value("${spotify-property.response_type}") String code,
#Value("${spotify-property.client_id}") String client_id,
#Value("${spotify-property.redirect_uri}") String redirect_uri,
#Value("${spotify-property.scope}") String scope,
#Value("${spotify-property.redirect_uri}") String show_dialog) {
this.code = code;
this.client_id = client_id;
this.redirect_uri = redirect_uri;
this.scope = scope;
this.show_dialog = show_dialog;
System.out.println(code); //works
}
public ResponseEntity<HttpHeaders> getSpotifyRedirectionCode() {
HttpHeaders headers = new HttpHeaders();
System.out.println(client_id); //doesn't work
System.out.println(this.code); //does not work either
System.out.println(redirect_uri);
System.out.println(scope);
System.out.println(show_dialog);
//more code doesn't matter
return new ResponseEntity<>(headers, HttpStatus.TEMPORARY_REDIRECT);
}
Why these variables are ok in constructor but in methods are null, how to set them in correct way? Also
#Value("${spotify-property.response_type}")
private final String code;
does not work either.
Your class fields are final so get instantiated without your configuration values.
You can either use the constructor as you have before, or remove the final from your fields.
I'm not sure if my answer is 100% correct. But I believe that you cannot change final variables. The right way would be to remove the final keyword and keep the #Value annotations on the fields and the you don't have to use it in the constructor.
#Service
#RequiredArgsConstructor
public class AuthorizationService {
#Value("${spotify-property.response_type}")
private String code;
#Value("${spotify-property.client_id}")
private String client_id;
#Value("${spotify-property.redirect_uri}")
private String redirect_uri;
#Value("${spotify-property.scope}")
private String scope;
#Value("${spotify-property.redirect_uri}")
private String show_dialog;
public ResponseEntity<HttpHeaders> getSpotifyRedirectionCode() {
HttpHeaders headers = new HttpHeaders();
System.out.println(client_id); //works
System.out.println(this.code); //works too
System.out.println(this.redirect_uri);
System.out.println(this.scope);
System.out.println(this.show_dialog);
//more code doesn't matter
return new ResponseEntity<>(headers, HttpStatus.TEMPORARY_REDIRECT);
} }

Spring/Jackson AutoMapping for field that can be multiple types

In my application, I am trying to get an OAuth token from multiple different providers.
According to the OAuth Spec, scopes should be sent as a string that contains a space delimited list of scopes.
However, I have noticed that some implementations return the scope as a List of strings.
In my application, I would like to store the scopes as a string that contains a space delimited list of scopes, as per the specification.
To do so, I created an Dto that looks as such (this dto is the same as the entity):
public class OAuthTokenDto {
// variables named to reflect OAuth Spec sends them to us
private String access_token;
private String refresh_token;
private Integer expires_in;
private String scope;
private String token_type;
public OAuthTokenDto() {
}
...
}
Is there a way to handle the fact that scopes might be sent as a List? In its current state, I am using rest template to do the mapping and it throws an exception because of this mismatch
You can make use of Jackson's #JsonAnyGetter and #JsonAnySetter. What you can do is, you can catch the unspecified tokens with this in which case your scope element and then typecast depending on the object type.
public class OAuthTokenDto {
// variables named to reflect OAuth Spec sends them to us
private String access_token;
private String refresh_token;
private Integer expires_in;
private String token_type;
#JsonIgnore
private Map<String, Object> properties = new HaspMap<String, Object>();
public OAuthTokenDto() {
}
#JsonAnyGetter
public Map<String, Object> getProperties() {
return this.properties;
}
#JsonAnySetter
public void setProperty(String name, Object value) {
this.properties.put(name, value);
}
}
And you can verify if your scope is an object or list of objects as follows
if(properites.get("scope") instanceof List<String>)
{
List<String> scopeList = properties.get("scope");
}
else
{
String scope = properties.get("scope");
}
Thanks to #Deadpool, the following implementation works
From jackson 2.6 you can use JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY
#JsonProperty("scope")
#JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
private String[] scope;
Clean solution:
Create converter class:
class ScopeConverter extends StdConverter<List<String>, String> {
#Override
public String convert(List<String> scopes) {
return scopes.stream().collect(Collectors.joining(" "));
}
}
Use it for scope property:
#JsonDeserialize(converter = ScopeConverter.class)
public String scope;
Enable:
mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
Now you can deserialize both cases scope being List and one element (with space separated scopes)

Spring data mongodb No mapping metadata found for java.lang.String error

I am trying to use spring data mongodb to retrieve a list of collections from the DB. However as soon as my code runs I get the following exception:
org.springframework.data.mapping.model.MappingException: No mapping metadata found for java.lang.String
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:209)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1008)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$100(MappingMongoConverter.java:75)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:957)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:924)
at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:78)
at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:63)
at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:70)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:232)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:212)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:176)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:172)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:75)
I can't seem to find the solution for this anywhere. Any help would be highly appreciated
Here is my java code which is used to retrieve the data:
public List<GateAppointment> listGateAppointments() {
List<GateAppointment> gateAppointments = null;
try{
MongoOperations mongoOperation = (MongoOperations)getMongoTemplate();
gateAppointments = mongoOperation.findAll(GateAppointment.class,COLLECTION_NAME);
}
catch(Exception e){
e.printStackTrace();
}
return gateAppointments;
}
And public static final String COLLECTION_NAME = "gateVisitAppointments";
The following is a sample of my DB data(Sorry, cant post image directly as I dont have 10 rep):
Please click to view DB Image
Following is my GateAppointment class file properties (The rest of the file has all the setters and getters):
package com.ig.avs.common.entity.db;
public class GateAppointment {
/**
* The Class GateAppointment.
*
*/
private String gate;
private String gateAppointmentNbr;
private String bol;
private String containerNbr;
private String iso;
private String line;
private String transactionType;
private String truckingCompany;
private String truckId;
private String appoinmentDate;
private String apSlot;
private String slotStartTime;
private String slotEndTime;
private String isMapped;
private String status;

Autocomplete using advanced model in wicket

First I want to say I saw a site:
https://cwiki.apache.org/WICKET/autocomplete-using-a-wicket-model.html
Still I have some problem with implementation.
Context
I have form where want to edit Order from my database.
I want to autocomplete client's name in form and save it to database.
Problem
I can see suggestions of client names and I can choose which client's name I'll use.
Just when I submit form new client won't be saved in order, in database.
I don't know how to relate form Model with AutoCompleteTextField input.
Any ideas ?
Pseudo code of my classes:
Order{
Long id;
String date;
Client client;
Status status;
...
}
Client{
Long id;
String name;
String nip;
String address;
String postcode;
String city;
String phone;
String mail;
...
}
Status{
Long id;
String name;
String value;
}
Edited:
Yes you are right.
My implementation of AbstractAutoCompleteTextField from site:
AbstractAutoCompleteRenderer autoCompleteRenderer = new AbstractAutoCompleteRenderer() {
protected final String getTextValue(final Object object) {
Client client = (Client) object;
return client.getName();
}
protected final void renderChoice(final Object object, final Response response, final String criteria) {
response.write(getTextValue(object));
}
};
// textfield
AbstractAutoCompleteTextField<Client> name = new AbstractAutoCompleteTextField<Client>("name", new PropertyModel(order, "client"), autoCompleteRenderer) {
protected final List<Client> getChoiceList(final String input) {
return clientService.findByNames(10, 0, input);
}
protected final String getChoiceValue(final Client choice) throws Throwable {
return choice.getId().toString();
}
};
form.add(name);
My form implementation you asked for:
form = new Form("orderForm", new CompoundPropertyModel(order)) {
#Override
public void onSubmit() {
orderService.update((Order) getDefaultModelObject());
setResponsePage(OrdersPage.class);
// Form validation successful. Display message showing edited
// model.
}
};
With this code I got: "'Hurtownia Techniczna "ADA"' is not proper Client." (translated from Polish) in feedback panel.
I think, that's where things go wrong:
AbstractAutoCompleteTextField<Client> name = new AbstractAutoCompleteTextField<Client>("name", new PropertyModel(order, "client"), autoCompleteRenderer)
Rest of the answer edited to reflect the correct use case
To be specific: You're creating a PropertyModel of your orders client value, which is a Client-Object and tie it to a TextField. To create a Client-object from the TextField, wicket needs a converter. There are lots of build-in converters but none of them is capable of converting to a custom object. Thus you'll need to provide the converter by implementing IConverter. Since I don't know how you store and retrieve your Client-objects I can only show you a generic example, a Locale-Converter used in one of my projects:
public class LocaleConverter implements IConverter {
private static final long serialVersionUID = 3251433094703013493L;
/* (non-Javadoc)
* #see org.apache.wicket.util.convert.IConverter#convertToObject(java.lang.String, java.util.Locale)
*/
#Override
public Object convertToObject(String value, Locale locale) {
Locale retValue = null;
try {
retValue = LocaleUtils.toLocale(value);
} catch (IllegalArgumentException e) {
throw (new ConversionException("" + value + " is not a valid locale.", e));
}
return retValue;
}
/* (non-Javadoc)
* #see org.apache.wicket.util.convert.IConverter#convertToString(java.lang.Object, java.util.Locale)
*/
#Override
public String convertToString(Object value, Locale locale) {
return value.toString();
}
}
Then you'll need to register your new converter to your application. Again, this will be slightly different for you since you've got a different converter...
#Override
protected IConverterLocator newConverterLocator() {
ConverterLocator newConverterLocator = (ConverterLocator) super.newConverterLocator();
newConverterLocator.set(Locale.class, new LocaleConverter());
return newConverterLocator;
}
This method needs to be included in your application class.

Resources