This is the sql script that I have used to create the necessary classes :
CREATE CLASS ProductSummary;
CREATE PROPERTY ProductSummary.name STRING (NOTNULL, MANDATORY TRUE);
CREATE PROPERTY ProductSummary.modelNumber LONG (NOTNULL, MANDATORY TRUE);
ALTER CLASS ProductSummary STRICTMODE TRUE;
CREATE CLASS PricingSummary;
CREATE PROPERTY PricingSummary.price LONG (NOTNULL, MANDATORY TRUE);
CREATE PROPERTY PricingSummary.discount LONG (NOTNULL, MANDATORY TRUE);
ALTER CLASS PricingSummary STRICTMODE TRUE;
CREATE CLASS TotalSummary EXTENDS V;
CREATE PROPERTY TotalSummary.projectLink LINK Project (NOTNULL, MANDATORY TRUE);
CREATE PROPERTY TotalSummary.productSummaries EMBEDDEDLIST ProductSummary;
CREATE PROPERTY TotalSummary.pricingSummaries EMBEDDEDLIST PricingSummary;
ALTER CLASS TotalSummary STRICTMODE TRUE;
CREATE INDEX TotalSummary_projectLink_idx ON TotalSummary (projectLink) UNIQUE;
I am trying to insert some values into my TotalSummary class, where I also need to insert some values into the EmbeddedList for pricingSummaries and productSummaries.
public TotalSummary create(final TotalSummary totalSummary) {
final Long projectId = 1;
final StatementBuilder builder = new StatementBuilder();
final StringBuilder query = new StringBuilder();
final List<Map<?, ?>> productSummaries = totalSummary.getProductSummaries().stream()
.map(ProductSummary::toMap)
.collect(Collectors.toList());
final List<Map<?, ?>> pricingSummaries = totalSummary.getPricingSummaries().stream()
.map(PricingSummary::toMap)
.collect(Collectors.toList());
builder.addAttribute("projectLink = (SELECT FROM project WHERE id = ?)", projectId);
if ( ! productSummaries.isEmpty()) {
builder.addAttribute("productSummaries = ?", productSummaries);
}
if ( ! pricingSummaries.isEmpty()) {
builder.addAttribute("pricingSummaries = ?", pricingSummaries);
}
try {
insert(TotalSummary.class.getSimpleName(), builder.attributes(), statement -> {
builder.init(statement);
return statement;
});
} catch (final UncategorizedSQLException e) {
throw new ConstraintViolationException(totalSummary, ExceptionUtils.getRootCauseMessage(e), e);
}
return assertNotNull(findById(projectId));
}
This is the utility method that I am using to build the insert query :
protected String insert(final String vertex, final String fieldValuePairs, final PreparedStatementInitializer initializer) {
final String sql = "INSERT INTO " + vertex + " SET " + fieldValuePairs + " RETURN #rid";
return executeStatement(sql, initializer);
}
The toMap methods to convert the List<ProductSummary> to List<Map<?,?>>
**ProductSummary**
public Map<String, Object> toMap() {
final Map<String, Object> ret = new HashMap<>();
ret.put("name", name);
ret.put("model number", Long.valueOf(modelNumber));
return ret;
}
The toMap methods to convert the List<PricingSummary> to List<Map<?,?>>
**PricingSummary**
public Map<String, Object> toMap() {
final Map<String, Object> ret = new HashMap<>();
ret.put("price", Long.valueOf(price));
ret.put("discount", Long.valueOf(discount));
return ret;
}
I am getting the following exception when I execute the code
Constraint violation for: TotalSummary#58f79eeb[recordId=<null>,customProperties=[]]. Reason: OValidationException: The field 'TotalSummary.productSummaries' has been declared as EMBEDDEDLIST but an incompatible type is used.
Things that I have already tried :
I have tried to covert to list to json format before adding it to
the builder like so new Gson().toJson(pricingSummaries);
Converted the pricingSummaries and productSummaries toArray().
You defined the summaries as EMBEDDEDLIST ProductSummary but you are passing lists of maps as values.
Try to create real ProductSummary objects instead eg.
OElement ret = db.newEmbeddedElement("ProductSummary");
ret.setProperty("price", Long.valueOf(price));
ret.setProperty("discount", Long.valueOf(discount));
Related
public Collection<OwnerDetail> getAllOwners() {
final MorphiaCursor<Listing> listings = datastore.find(Listing.class)
.iterator(new FindOptions()
.projection().include("ownerDetail"));
Map<String, OwnerDetail> map = new HashMap<>();
while (listings.hasNext()) {
final Listing next = listings.next();
if (next.getOwnerDetail() != null) {
map.put(next.getOwnerDetail().getEmail(), next.getOwnerDetail());
}
}
return map.values();
}
I want to remove java code that distinct values by email and handle it by mongodb morphia. How can I do that?
Am trying to get data from 3 tables and every time I end up getting an error
Ljava.lang.Object; cannot be cast to .model.ISECO at
java.util.ArrayList.forEach
This are my entities
#Entity
public class IS01 {
private String IEA;
private String INUM;
private String ILINE;
private String I0103;
#Entity
public class ISOVER {
private String IEA;
private String ILINE;
private String INUM;
private String IRESULT;
private String ICON;
private String IBCON;
private String CASE;
private String RPTID
#Entity
public class POSTCO {
private String CEA;
private String CNUM;
private String CLINE;
private String PSCONTACT;
And this is my Repository
public interface LineSummary extends CrudRepository<ISOVER , String> {
#Query("select c.ILINE , c.IRESULT,e.PSCONTACT, \n" +
"c.ICON,c.IBCON, c.RPTID, c.CASE, d.i0103 as age\n" +
"FROM ISOVER c \n" +
"inner join IS01 d \n" +
"on c.IEA = d.IEA and c.INUM = d.INUM and c.ILINE = d.ILINE\n" +
"inner join POSTCO e on d.IEA = e.CEA and d.INUM = e.CNUM and d.ILINE = e.CLINE\n" +
"where c.CASE like %?1%")
Iterable<ISOVER> findEntriesByUserId(#Param("Case") String Case);
And this is my service
public ResponseEntity<Map<String, Object>> retrieveLineListingSQL(String Case){
Iterable <ISOVER > stud = lineSummary.findEntriesByUserId(Case);
Map<String, Object> parents = new HashMap<>();
parents.put("totalMembers", 9);
parents.put("questionaryinfo", new ArrayList<HashMap<String,Object>>());
ArrayList<HashMap<String,Object>> listings = (ArrayList<HashMap<String,Object>>) parents.get("questionaryinfo");
if (stud != null) {
stud.forEach(d -> {
HashMap<String,Object> entry = new HashMap<>();
entry.put("adultquestionary","Yes");
entry.put("caseNumber", d.getCASE());
listings.add(entry);
});
}
parents.put("DMStatus", "No review");
parents.put("ages", new HashMap<String, Object>());
return ResponseEntity.ok().body(parents);
}
How can I return the results from the query and map them accordingly?
I believe this is your culprit:
if (stud != null) {
stud.forEach(d -> {
HashMap<String, Object> entry = new HashMap<>(); // < -- here
entry.put("adultquestionary","Yes");
entry.put("caseNumber", d.getCASE());
listings.add(entry);
});
}
Have your tried using *.model.ISECO instead of java.lang.Object? Does that work, any particular limitation?
Additionally, you could refactor you code to something way more simple, if you follow the same explanation provided in here: How to make nested JSON response with Array from a Stored procedure
Create a response model that outputs the format you expect as response.
There is no need for you to do all that collections handling one-by-one. The representation of an object in JSON is a MAP, basically let the
Jackson JSON library do all that work for you.
I'm trying to migrate an old project to Retrofit library and this project has quite tricky API. So I have a query template like this:
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch();
And I have to add some parameters here of following template:
filter[attributeId]=attributeValueId
For example:
products/search?filter[1]=10&filter[1]=11&filter[2]=20&filter[2]=21
That's how API works and I can't change it. I know that we can pass a list as a parameter, like this:
#Query("filter") List<Integer> attributeValueIds
But how can I also set parameter's name dynamically?
You can use an arrayList! Something like the code below.
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch(
#Query("status") List<Integer> status
);
ArrayList<Integer> queryStatus = new ArrayList<>();
queryStatus.add(0);
queryStatus.add(1);
queryStatus.add(2);
productService.productSearch(queryStatus);
Your url will be like that -> {url}?status=0&status=1&status=2
Thanks to the link, posted by #ILLIA DEREVIANKO (https://github.com/square/retrofit/issues/1324), I've managed to solve the problem with this class:
public class ProxyRetrofitQueryMap extends HashMap<String, Object> {
public ProxyRetrofitQueryMap(Map<String, Object> m) {
super(m);
}
#Override
public Set<Entry<String, Object>> entrySet() {
Set<Entry<String, Object>> originSet = super.entrySet();
Set<Entry<String, Object>> newSet = new HashSet<>();
for (Entry<String, Object> entry : originSet) {
String entryKey = entry.getKey();
if (entryKey == null) {
throw new IllegalArgumentException("Query map contained null key.");
}
Object entryValue = entry.getValue();
if (entryValue == null) {
throw new IllegalArgumentException(
"Query map contained null value for key '" + entryKey + "'.");
}
else if(entryValue instanceof List) {
for(Object arrayValue:(List)entryValue) {
if (arrayValue != null) { // Skip null values
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, arrayValue);
newSet.add(newEntry);
}
}
}
else {
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, entryValue);
newSet.add(newEntry);
}
}
return newSet;
}
}
With this we can just use a map, where key is a unique parameter name and value is a List of Strings, that are values for this parameter. Something like this:
ProxyRetrofitQueryMap map = new ProxyRetrofitQueryMap();
List<String> values1 = new ArrayList<>();
values1.add("10");
values1.add("11");
map.put("filter[1]", values1);
List<String> values2 = new ArrayList<>();
values1.add("20");
values1.add("21");
map.put("filter[2]", values2);
You can use #QueryMap annotation like this:
public interface NewsService() {
#GET("/news")
Call<List<News>> getNews(
#QueryMap Map<String, String> options
);
}
Map<String, String> data = new HashMap<>();
data.put("author", "Marcus");
data.put("page", String.valueOf(2));
...
newsService.getNews(data);
More details: https://futurestud.io/tutorials/retrofit-2-add-multiple-query-parameter-with-querymap
I've build a cache that returns a value in list format when you enter the parameters. If that value is not in the cache, it goes to the database and retrieves it, putting it in the cache for future reference:
private ProfileDAO profileDAO;
private String[] temp;
private LoadingCache<String, List<Profile>> loadingCache = CacheBuilder.newBuilder()
.refreshAfterWrite(5, TimeUnit.MINUTES)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build(
new CacheLoader<String, List<Profile>>() {
#Override
public List<Profile> load(String key) throws Exception {
logger.info("Running method to retrieve from database");
temp = key.split("\\|");
String instance = temp[0];
String name = temp[1];
List<Profile> profiles= profileDAO.getProfileByFields(id, name);
if (profiles.isEmpty()) {
List<Profile> nullValue = new ArrayList<Profile>();
logger.info("Unable to find a value.");
return nullValue;
}
logger.info("Found a value");
return profileDAO.getProfileByFields(id, name);
}
}
);
public List<Profile> getProfileByFields(String id, String name) throws Exception {
String key = id.toLowerCase() + "|" + name.toLowerCase()
return loadingCache.get(key);
}
This seems to work fine, but it does not take into account null values. If I look for an entry that does not exist, I get an exception for :
com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key A01|Peter
I'd like to simply return an empty List(Profile) if there is no match in the database, but my if statement has failed. Is there any way around this error for this particular use case?
Though this feels a bit hacky, I think it's a more complete solution (Suresh's answer only really applies to collections).
Define a singleton object that will represent null, and insert that value into the cache instead of null (converting to null at retrieval time):
class MyDAO
{
static final Object NULL = new Object();
LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
.build( new CacheLoader<>()
{
public Object load( String key )
{
Object value = database.get( key );
if( value == null )
return NULL;
return value;
}
});
Object get( String key )
{
Object value = cache.get( key );
if( value == NULL ) // use '==' to compare object references
return null;
return value;
}
}
I believe this approach is preferable, in terms of efficiency, to any involving the use of exceptions.
Using Optional class Optional<Object> as the cache value is the easiest and cleanest way to do it.
Make changes in your code to check first profiles is null or not as(using profiles == null ...) :
private ProfileDAO profileDAO;
private String[] temp;
private LoadingCache<String, List<Profile>> loadingCache = CacheBuilder.newBuilder()
.refreshAfterWrite(5, TimeUnit.MINUTES)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build(
new CacheLoader<String, List<Profile>>() {
#Override
public List<Profile> load(String key) throws Exception {
logger.info("Running method to retrieve from database");
temp = key.split("\\|");
String instance = temp[0];
String name = temp[1];
List<Profile> profiles= profileDAO.getProfileByFields(id, name);
if (profiles == null || profiles.isEmpty()) {
List<Profile> nullValue = new ArrayList<Profile>();
logger.info("Unable to find a value.");
return nullValue;
}
logger.info("Found a value");
return profileDAO.getProfileByFields(id, name);
}
}
);
public List<Profile> getProfileByFields(String id, String name) throws Exception {
String key = id.toLowerCase() + "|" + name.toLowerCase()
return loadingCache.get(key);
}
Please check this code is working for you null values or not..
I am able to create order using square(v2/locations/location_id/orders)api and getting order id. But I am not able to get this order details and also how I can see this created order on square dashboard? please help me.
I am using the below method for doing it:
public CreateOrderResponse createOrder(String locationId, CreateOrderRequest body) throws ApiException {
Object localVarPostBody = body;
// verify the required parameter 'locationId' is set
if (locationId == null) {
throw new ApiException(400, "Missing the required parameter 'locationId' when calling createOrder");
}
// verify the required parameter 'body' is set
if (body == null) {
throw new ApiException(400, "Missing the required parameter 'body' when calling createOrder");
}
// create path and map variables
String localVarPath = "/v2/locations/{location_id}/orders".replaceAll("\\{" + "location_id" + "\\}",
apiClient.escapeString(locationId.toString()));
// query params
List<Pair> localVarQueryParams = new ArrayList<Pair>();
Map<String, String> localVarHeaderParams = new HashMap<String, String>();
Map<String, Object> localVarFormParams = new HashMap<String, Object>();
final String[] localVarAccepts = { "application/json" };
final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = { "application/json" };
final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { "oauth2" };
GenericType<CreateOrderResponse> localVarReturnType = new GenericType<CreateOrderResponse>() {
};
CompleteResponse<CreateOrderResponse> completeResponse = (CompleteResponse<CreateOrderResponse>) apiClient
.invokeAPI(localVarPath, "POST", localVarQueryParams, localVarPostBody, localVarHeaderParams,
localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames,
localVarReturnType);
return completeResponse.getData();
}
Thanks
The orders endpoint is only for creating itemized orders for e-commerce transactions. You won't see them anywhere until you charge them, and then you'll see the itemizations for the order in your dashboard with the transaction.