I am developing an application using GeoModel. I need to perform search in a particular radius based on the given latitude and longitude. I am able to generate the GeoCells in the datastore using Objectify, but not able to get back the results in a particular radius.
I am sharing my code below.
Entity Class
#Entity
public class NewsFeed implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Index
private Long feedID;
#Index
private String topic;
#Index
private String title;
private String description;
#Index
private Date createDate;
private String imageOrVideo;
private String imageUrl;
private String blobKey;
#Latitude
private Double latitude;
#Longitude
private Double longitude;
#Geocells
private List<String> cells;
// getter and setters ...
}
Custom GeocellQueryEngine Class From This Source
public class ObjectifyGeocellQueryEngine implements GeocellQueryEngine {
private String geocellsProperty;
private Objectify ofy;
public static final String DEFAULT_GEOCELLS_PROPERTY = "cells";
public ObjectifyGeocellQueryEngine(Objectify ofy) {
this(ofy, DEFAULT_GEOCELLS_PROPERTY);
}
public ObjectifyGeocellQueryEngine(Objectify ofy, String geocellsProperty) {
this.ofy = ofy;
this.geocellsProperty = geocellsProperty;
}
#Override
public <T> List<T> query(GeocellQuery baseQuery, List<String> geocells, Class<T> entityClass) {
StringTokenizer st;
int tokenNo = 0;
Query<T> query = ofy.query(entityClass);
if (baseQuery != null) {
st = new StringTokenizer(baseQuery.getBaseQuery(), ",");
while (st.hasMoreTokens()) {
query.filter(st.nextToken(), baseQuery.getParameters().get(tokenNo++));
}
}
return query.filter(geocellsProperty + " IN", geocells).list();
}
}
Fetching Data Here
Point p = new Point(24.8993714, 79.5839124);
// Generates the list of GeoCells
List<String> cells = GeocellManager.generateGeoCell(p);
List<Object> params = new ArrayList<Object>();
params.add("Movies");
GeocellQuery baseQuery = new GeocellQuery("topic == topic", "String topic",params);
ObjectifyGeocellQueryEngine objectifyGeocellQueryEngine = new ObjectifyGeocellQueryEngine(ofy(), "cells");
List<NewsFeed> list = objectifyGeocellQueryEngine.query(baseQuery, cells, NewsFeed.class);
List<NewsFeed> list2 = GeocellManager.proximitySearch(p, 10, 10000,NewsFeed.class, baseQuery, objectifyGeocellQueryEngine, GeocellManager.MAX_GEOCELL_RESOLUTION);
System.out.println(list+" : "+list2);
Now the problem is I am not getting any results out from here. Can you people please help me with this as I am not getting any exception, just getting the empty list.
I have done a workaround for this situation I have added a parallel JDO Class to store and retrieve the geospatial results.
Related
I'm working on a simple spring boot project.
I have this Dto class called TaskDto:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class TaskDto {
private int releveBancaireId;
private String variableName;
private String variableTypeName;
private String proccessesName;
private String id;
private String assignee;
private String name;
private String description;
private int priority;
private String processDefinitionId;
private String processInstanceId;
private Date createTime;
}
I also have a service which loops over something called Tasks, collects the data and sets it into TaskDto.
List<Task> taskList = taskService.createTaskQuery().taskAssignee(assignee).list();
String finalVariableName = variableName;
String finalVariableTypeName = variableTypeName;
return taskList.stream().map(task -> {
TaskDto taskDto = new TaskDto();
String releveBancaireIdInsideForLoop = null;
for (Task taskLoop: tasks) {
Map<String, Object> variables = taskLoop.getProcessVariables();
for (Entry<String, Object> stringObjectEntry: variables.entrySet()) {
releveBancaireIdInsideForLoop = stringObjectEntry.getValue().toString();
System.out.println("displaying releveBancaireIdInsideForLoop " + releveBancaireIdInsideForLoop);
taskDto.setReleveBancaireId(Integer.parseInt(releveBancaireIdInsideForLoop));
taskDto.setVariableName(finalVariableName);
taskDto.setVariableTypeName(finalVariableTypeName);
taskDto.setProccessesName(processDefinition.getName());
taskDto.setId(task.getId());
taskDto.setAssignee(task.getAssignee());
taskDto.setName(task.getName());
taskDto.setDescription(task.getDescription());
taskDto.setPriority(task.getPriority());
taskDto.setProcessDefinitionId(task.getProcessDefinitionId());
taskDto.setCreateTime(task.getCreateTime());
System.out.println("shwoing task dto " + taskDto);
}
}
return taskDto;
}
To simplify the issue, I have 2 Tasks. Each Task has a variable that I need, so what I'm doing is looping over them and collect the value that I want. For example, in the first loop it displays:
releveBancaireIdInsideForLoop = 1
while in the second loop shows
releveBancaireIdInsideForLoop = 2
Then, when I try to do
taskDto.setReleveBancaireId(Integer.parseInt(releveBancaireIdInsideForLoop));
It shows me on the terminal two TaskDtos with the same value (value 2 from the last loop) instead of 1 and 2. I don't know if this is the right way to set values dynamically.
I need to get some specific data from rest to my model.
Data I get from rest :
[{"id":595,"name":"TransXChange20210805113332","prosystem_file_id":null,"dataset":16,"creator":113,"editor":113,"created":"2021-08-05T09:45:21.444949Z","edited":"2021-08-05T09:45:27.542152Z","update_from_url":false,"description":"Rozkłady jazdy komunikacji miejskiej ważne od 08.08.2021","file":"https://otwartedane.erzeszow.pl/media/resources/transxchange20210805113332.xml","link":null,"extension":"XML","data_type":"[]","file_name":"transxchange20210805113332.xml","chart_info":null,"map_info":null,"score":4,"public":true,"licence":"other-open","connection_dict":null,"selection_string":null,"db_type":"POSTGRESQL","type":"file","dbview_cache_minutes":1,"preview_base64":null,"gpkg_display_info":null,"archive_to_csv":false},{"id":538,"name":"TransXChange20210513082611","prosystem_file_id":null,"dataset":16,"creator":113,"editor":113,"created":"2021-05-13T06:28:50.233464Z","edited":"2021-07-28T08:52:06.695966Z","update_from_url":false,"description":"Rozkłady jazdy komunikacji miejskiej ważne od 15.05.2021","file":"https://otwartedane.erzeszow.pl/media/resources/transxchange20210513082611.xml","link":null,"extension":"XML","data_type":"[]","file_name":"transxchange20210513082611.xml","chart_info":null,"map_info":null,"score":4,"public":true,"licence":"other-open","connection_dict":null,"selection_string":null,"db_type":"POSTGRESQL","type":"file","dbview_cache_minutes":1,"preview_base64":null,"gpkg_display_info":null,"archive_to_csv":false},{"id":544,"name":"TransXChange20210526143716","prosystem_file_id":null,"dataset":16,"creator":113,"editor":113,"created":"2021-05-26T12:40:42.587492Z","edited":"2021-07-28T08:52:04.417450Z","update_from_url":false,"description":"Rozkłady jazdy komunikacji miejskiej ważne od 01.06.2021","file":"https://otwartedane.erzeszow.pl/media/resources/transxchange20210526143716.xml","link":null,"extension":"XML","data_type":"[]","file_name":"transxchange20210526143716.xml","chart_info":null,"map_info":null,"score":4,"public":true,"licence":"other-open","connection_dict":null,"selection_string":null,"db_type":"POSTGRESQL","type":"file","dbview_cache_minutes":1,"preview_base64":null,"gpkg_display_info":null,"archive_to_csv":false}]
i got it in single line
my code in java :
RestTemplateBuilder builder = new RestTemplateBuilder();
String soc = builder.build().getForObject("https://otwartedane.erzeszow.pl/v1/datasets/16/resources/", String.class);
assert soc != null;
System.out.println(soc);
And the problem is I need to put them into model
My model:
public class Resource {
private long id;
private String name;
private long prosystem_file_id;
private int dataset;
private int creator;
private int editor;
private LocalDateTime created;
private LocalDateTime edited;
private boolean update_from_url;
private String description;
private String file;
private String link;
private String extension;
private String data_type;
private String file_name;
private String chart_info;
private String map_info;
private int score;
private boolean isPublic;
private String licence;
private String connection_dict;
private String selection_string;
private String db_type;
private String type;
private int dbview_cache_minutes;
private String preview_base64;
private String gpkg_display_info;
private boolean archive_to_csv;
All getters and setters are generated.
How can I put them into model for example List?
The problem is I get data like [{resource},{resource},{resource}].
As it states from the RestTemplate documentation
you can call to the getForObject method passing as an argument the desired deserialization class.
Something like:
RestTemplateBuilder builder = new RestTemplateBuilder();
Resource soc = builder.build().getForObject("https://otwartedane.erzeszow.pl/v1/datasets/16/resources/", Resource.class);
assert soc != null;
System.out.println(soc);
I have found answer to my question.
I need to assign my call to array of model.
Resource[] soc =builder.build().getForObject( URL , Resource[].class );
I have the following CriteriaQuery that I use to filter orders.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<OrderReducedDTO> cq = cb.createQuery(OrderReducedDTO.class);
Root<Order> root = cq.from(Order.class);
Join<Order, Customer> joinCustomer = root.join(Order_.customer);
Join<Order, Shipment> joinShipment = root.join(Order_.shipment);
Join<Shipment, Carrier> joinCarrier = joinShipment.join(Shipment_.carrier);
Join<Order, Payment> joinPayment = root.join(Order_.payment);
Join<Payment, PaymentMethod> joinPaymentMethod = joinPayment.join(Payment_.paymentMethod);
Join<Shipment, Country> joinCountry = joinShipment.join(Shipment_.country);
cq.select(cb.construct(
OrderReducedDTO.class,
root.get(Order_.id),
root.get(Order_.incrementId),
root.get(Order_.state),
root.get(Order_.couponCode),
root.get(Order_.totalDiscount),
root.get(Order_.total),
root.get(Order_.originChannel),
root.get(Order_.branchOffice),
joinCarrier.get(Carrier_.carrierCode),
cb.function("CONCAT_WS", String.class,
cb.literal(","),
joinShipment.get(Shipment_.streetName),
joinShipment.get(Shipment_.streetNumber),
joinShipment.get(Shipment_.city),
joinCountry.get(Country_.name),
joinShipment.get(Shipment_.zipCode)
),
joinPaymentMethod.get(PaymentMethod_.code),
joinPayment.get(Payment_.paymentDate),
root.get(Order_.createdAt),
root.get(Order_.updatedAt),
root.get(Order_.externalId),
joinCustomer.get(Customer_.fullName)
));
... filters and predicates...
The part that's giving me trouble and causing a NPE to be thrown is this
cb.function("CONCAT_WS", String.class,
cb.literal(","),
joinShipment.get(Shipment_.streetName),
joinShipment.get(Shipment_.streetNumber),
joinShipment.get(Shipment_.city),
joinCountry.get(Country_.name),
joinShipment.get(Shipment_.zipCode)
)
More, specifically, when I use the CONCAT_WS function. If I use CONCAT, it works.
This is the stacktrace I get:
java.lang.NullPointerException: null
at org.hibernate.hql.internal.NameGenerator.generateColumnNames(NameGenerator.java:27)
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.generateColumnNames(SessionFactoryHelper.java:434)
at org.hibernate.hql.internal.ast.tree.SelectClause.initializeColumnNames(SelectClause.java:270)
at org.hibernate.hql.internal.ast.tree.SelectClause.finishInitialization(SelectClause.java:260)
at org.hibernate.hql.internal.ast.tree.SelectClause.initializeExplicitSelectClause(SelectClause.java:255)
at org.hibernate.hql.internal.ast.HqlSqlWalker.useSelectClause(HqlSqlWalker.java:1026)
...
This is my OrderReducedDTO
#Getter
public class OrderReducedDTO {
#JsonProperty("order_id")
private Integer orderId;
#JsonProperty("increment_id")
private String incrementId;
private OrderStates state;
#JsonProperty("coupon_code")
private String couponCode;
#JsonProperty("total_discount")
private BigDecimal totalDiscount;
private BigDecimal total;
#JsonProperty("origin_channel")
private String originChannel;
#JsonProperty("branch_office")
private String branchOffice;
#JsonProperty("shipping_method")
private String shippingMethod;
#JsonProperty("shipping_address")
private String shippingAddress;
#JsonProperty("payment_method")
private String paymentMethod;
#JsonProperty("payment_date")
private Timestamp paymentDate;
#JsonProperty("created_at")
private Timestamp createdAt;
#JsonProperty("updated_at")
private Timestamp updatedAt;
#JsonProperty("external_id")
private String externalId;
#JsonProperty("customer_full_name")
private String customerFullName;
#Setter
private List<OrderProductReducedDTO> products;
public OrderReducedDTO(Integer orderId,
String incrementId,
OrderStates state,
String couponCode,
BigDecimal totalDiscount,
BigDecimal total,
String originChannel,
String branchOffice,
String shippingMethod,
String shippingAddress,
String paymentMethod,
Object paymentDate,
Object createdAt,
Object updatedAt,
String externalId,
String customerFullName) {
this.orderId = orderId;
this.incrementId = incrementId;
this.state = state;
this.couponCode = couponCode;
this.totalDiscount = totalDiscount;
this.total = total;
this.originChannel = originChannel;
this.branchOffice = branchOffice;
this.shippingMethod = shippingMethod;
this.shippingAddress = shippingAddress;
this.paymentMethod = paymentMethod;
this.paymentDate = (Timestamp) paymentDate;
this.createdAt = (Timestamp) createdAt; //https://hibernate.atlassian.net/browse/HHH-4179
this.updatedAt = (Timestamp) updatedAt;
this.externalId = externalId;
this.customerFullName = customerFullName;
}
}
What I mainly want to know is if I'm using the function method correctly. I assume I am because CONCAT works.
After hours of debugging within Hibernate, I finally arrived at the root of the problem:
org/hibernate/hql/internal/ast/tree/ConstructorNode.java
private Type[] resolveConstructorArgumentTypes() throws SemanticException {
SelectExpression[] argumentExpressions = this.collectSelectExpressions();
if (argumentExpressions == null) {
return new Type[0];
} else {
Type[] types = new Type[argumentExpressions.length];
for(int x = 0; x < argumentExpressions.length; ++x) {
types[x] = argumentExpressions[x].getDataType();
}
return types;
}
}
argumentExpressions[x].getDataType() was returning null.
I googled and found out that this could be caused by Hibernate not knowing the actual return type of the given SQL function (apparently it only knows the most common ones).
I then followed this answer and implemented a custom MetadataBuilderContributor like so:
public class SqlFunctionsMetadataBuilderContributor implements MetadataBuilderContributor {
#Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applySqlFunction(
"concat_ws",
new StandardSQLFunction("concat_ws", StandardBasicTypes.STRING)
);
}
}
And on my application.properties I added:
spring.jpa.properties.hibernate.metadata_builder_contributor=ar.com.glamit.glamitoms.config.hibernate.SqlFunctionsMetadataBuilderContributor
After relaunching the app, argumentExpressions[x].getDataType() now returns a StringType and the NullPointerException is gone.
I started using Project Reactor recently and I can't work out how to work with nested streams. I want to update data of outer Mono with some data of inner Mono.
#GetMapping("/search")
public Mono<Github> combineGithubData() {
WebClient client = WebClient.create("https://api.github.com");
Mono<Github> data = client.get().uri(URI.create("https://api.github.com/users/autocorrectoff")).retrieve().bodyToMono(Github.class);
data = data.map(s -> {
client.get().uri(URI.create("https://api.github.com/users/Kukilej")).retrieve().bodyToMono(Github.class).map(m -> {
s.setXXX(m.getName());
return m;
});
return s;
});
return data;
}
The field XXX is always returned as null, although I have set it to a value from inner Mono. I'm pretty sure this would work in RxJs. How do I make this work with Project Reactor?
edit:
the code of the Github class
import lombok.*;
#Getter #Setter
#Builder
#ToString
#NoArgsConstructor
#AllArgsConstructor
public class Github {
private String login;
private int id;
private String node_id;
private String avatar_url;
private String gravatar_id;
private String url;
private String html_url;
private String followers_url;
private String following_url;
private String gists_url;
private String starred_url;
private String subscriptions_url;
private String organizations_url;
private String repos_url;
private String events_url;
private String received_events_url;
private String type;
private boolean site_admin;
private String name;
private String company;
private String blog;
private String location;
private String email;
private String hireable;
private String bio;
private int public_repos;
private int public_gists;
private int followers;
private int following;
private String created_at;
private String updated_at;
private String XXX;
}
Your inner stream is not getting subscribed to. Either us flatMap, or better yet, use zip:
data
.zipWith(client.get().uri(...).retrieve().bodyToMono(Github.class))
.map(tuple2 -> {
//update tuple2.getT1() with m.getName() and return the updated tuple
return tuple2.mapT1(tuple2.getT1().setXXX(tuple2.getT2().getName()));
})
.map(tuple2 -> tuple2.getT1() //updated s);
zipWith() subscribes to the inner stream.
I have a POJO class:
#Entity
#Table(name = "interruttori", catalog = "SMARTPARK")
public class Interruttore implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private int idInterruttore;
private int numeroInterruttore;
private String nomeInterruttore;
private String descrizione;
private List<Luce> luci;
private String pinName;
private boolean remoto;
private boolean stato;
private Date dateTime;
private Set<Integer> activeSensors = new HashSet<Integer>();
//getters and setters and specifically
#Transient
public Set<Integer> getActiveSensors() {
return activeSensors;
}
public void setActiveSensors(Set<Integer> activeSensors) {
this.activeSensors = activeSensors;
}
It's #Transient because I don't want to persist the Set, i need it just as a "counter" in a Controller.
The controller part we need is:
#RequestMapping(value="/sensoristica")
public ResponseEntity<Sensoristica> findIlluminazione(#RequestParam(value="idLuce") int idLuce,
#RequestParam(value="lit") boolean lit,
#RequestParam(value="suServer") boolean suServer) {
Sensoristica sensoristica = new Sensoristica();
Luce luce = luceService.findById(idLuce);
String nomeLuce = luce.getNomeLuce();
int numeroLuce = luce.getNumeroLuce();
sensoristica.setLuce(luce);
sensoristica.setLit(lit);
sensoristicaService.saveSensoristica(sensoristica);
logger.debug("Aggiornato sensore " + numeroLuce + " ("+nomeLuce+") acceso: "+lit);
//aggiorniamo lo stato del sensore
luce.setLit(lit);
luceService.updateLuce(luce);
//qui gestisco l'interruttore
if(suServer){
int idInterruttore = luce.getInterruttore().getIdInterruttore();
Interruttore interruttore = interruttoreService.findById(idInterruttore);
Set<Integer> activeSensors = interruttore.getActiveSensors();
logger.debug("Active sensor è " +activeSensors);
if(lit){
activeSensors.add(idLuce);
logger.debug("Aggiungo id "+idLuce);
logger.debug("Active è lungo: "+activeSensors.size());
} else {
if (activeSensors.contains(idLuce)){
activeSensors.remove(idLuce);
logger.debug("Rimuovo id "+idLuce);
logger.debug("Active è lungo: "+activeSensors.size());
}
}
interruttore.setActiveSensors(activeSensors);
interruttoreService.updateInterruttore(interruttore);
boolean canShutDown = activeSensors.isEmpty();
logger.debug("canShutDown is "+canShutDown);
Basically, I want to add or remove idLuceto the Set and then check if activeSensors.isEmpty().
The problem is that every call to the Controller gives me back an empty Set, not a Set with the previous idLuces inside.
How can I obtain it?
Actually #Transient should be applied according to AccessType.
Please try setting #Transient to the field.
#Transient
private Set<Integer> activeSensors = new HashSet<Integer>();