I am trying to parse json structure https://developers.nest.com/documentation/api-reference
Where device could be various types i want jackson to instantiate relevant objects Thermostat/SmokeAlarm,Camera etc
#Data
#ToString
public class Nest {
#JsonProperty("metadata")
private Metadata metadata;
#JsonProperty("structures")
private HashMap<String, Structure> structures;
#JsonProperty("devices")
private HashMap<String, HashMap<String, Device>> devices;
}
How would i use#JsonTypeinfo to decided which type to instatntite based on values in keys.
Another question would be how woul i get rid of all these multilevel nestings and cal have something like
#JsonProperty("devices")
private List<Device> devices;
parsed according to keys/subtypes
Related
I have multiple existing Stateful Session Beans. I want to use a new library/framework that instantiates objects (outside the container manager). This framework does not conceptually have 'sessions'. I'm trying to develop a proof of concept to route calling of beans in different session contexts based on a map of session identifiers to session contexts.
Below are 2 handlers that are instantiated by the library. The first handler creates new BoundSessionContexts and maps them to generated keys. The second handler is suppose to be passed the key and based on it propagate to the appropriate corresponding sessionContext, lookup the beans in that context, and call those beans.
public class Handler1 implements Handler1Interface{
//**1**
WeldManager weldManager = (WeldManager) CDI.current().getBeanManager();
BoundSessionContext boundSessionCtx;
//**2**
Map<String, Object> sessionMap = new HashMap<>();
public Handler1(){
}
//**3**
#Override
public long start(){
long sessionId = new Random().nextLong();
//**4**
boundSessionCtx = weldManager.instance().select(BoundSessionContext.class, BoundLiteral.INSTANCE).get();
//**5**
//boundSessionCtx.associate(sessionMap);
//Make certain the sessionId isn't already in use.
while(SessionMapper.get(sessionId)!=null){
sessionId = new Random().nextLong();
}
//**6**
SessionMapper.put(sessionId, boundSessionCtx);
return sessionId;
}
//**7**
#Override
public void stop(long sessionId){
SessionMapper.remove(sessionId);
}
}
public class Handler2 implements Handler1Interface{
//**8**
#Inject
EJB1 ejb1;
//**9**
#Inject
EJB2 ejb2;
BeanManager beanManager;
BoundSessionContext boundSessionCxt;
//**10**
Map<String, Object> sessionMap = new HashMap<>();
public Handler2(){
}
#Override
public Object process(long sessionId, Object input){
lookupEJBs(sessionId);
//**11**
ejb1.method();
Object result = ejb2.method();
return result;
}
//**12**
private void lookupEJBs(long sessionId) {
boundSessionCxt = SessionMapper.get(sessionId);
boundSessionCxt.associate(sessionMap);
boundSessionCxt.activate();
beanManager = CDI.current().getBeanManager();
//**13**
TypeLiteral<EJB1> typeLiteral = new TypeLiteral<EJB1>() {};
Set<Bean<?>> beans = beanManager.getBeans(typeLiteral.getType());
Bean<?> bean = beanManager.resolve(beans);
ejb1 = bean.create(boundSessionCxt);
//**14**
TypeLiteral<EJB2> typeLiteral2 = new TypeLiteral<EJB2>() {};
beans = beanManager.getBeans(typeLiteral2.getType());
bean = beanManager.resolve(beans);
ejb2 = bean.create(boundSessionCxt);
}
I've never been able to call ejb2.method(). While I have used EJBs for many years this is my first attempt at manipulating contexts. I am definitively feeling lost. It's one thing to use the magic, it's another to warp that magic to your whim.
Questions (In no particular order):
A) Is what I'm trying to do 'reasonably' acheivable? Or is this a pipe dream? NOTE: I am currently using WELD-API 3.0.SP4, but I am not married to it.
B) I have never truly understood the reason for the map(10) that is associated with a context(12).
B1) What is it's purpose?
B2) How does it's use affect what I'm trying to do here?
B3) Am I correct in that I would want to associate and activate the context inside the object where I want to use the context beans?
C) Am I correct that #Inject (8 and 9) is pointless as the handler2 object is not instantiated/Injected by the bean manager.
Many thanks to anyone who can help me understand EJB/CDI session contexts better. :)
Given
public class Person {
public final StringProperty name = new SimpleStringProperty();
}
Is there any way to map an ObservableList<Person> to an ObservableList<String> without implementing a ListChangeListener<Person> to manually update the required list?
I've found a library which does the trick:
https://github.com/tobiasdiez/EasyBind
It provides EasyBind.map with this exact functionality with a side note that the performed mapping function is executed on every get(int index), which decreases initial setup.
EasyBind.mapBacked provides an ObservableList in which the mapping function is already applied to every item, which may be preferable for intensive mapping functions.
I have a private list and I don't want that it can be modified from outside in general. Just adding from outside is allowed and only if the object is valid. Therefore I used to write it like this:
private List<Object> list = new ArrayList<>();
public List<Object> getList()
{
return Collections.unmodifiableList(list);
}
public void addObject(Object object)
{
if (isObjectValid(object)) //any validation
list.add(object);
}
Now for JavaFX purposes I turn the list to a property:
private ListProperty<Object> list =
new SimpleListProperty<>(FXCollections.observableArrayList());
To profit from the benefits of an property like data binding and the ListChangeListener I have to provide the property to the outer world. But then access to all methods of a list is provided, too. (To use a ReadOnlyListProperty has no effect since the list instance itself will never change.) What can I do to achieve all goals:
private ListProperty
ListChangeListener can be added from outside
Usable for binding dependencies from outside (the create methods form class Bindings)
No modifying of the property or list instance itself
Modifying of list content from outside only through my own methods
Not tested, but try:
private ListProperty<Object> list = new SimpleListProperty<>(FXCollections.observableArrayList());
private ReadOnlyListWrapper<Object> publicList = new ReadOnlyListWrapper<>();
and in the constructor:
publicList.bind(Bindings.createObjectBinding(
() -> FXCollections.unmodifiableObservableList(list.getValue()),
list));
then your accessor method is
public ReadOnlyListProperty<Object> getList() {
return publicList.getReadOnlyProperty();
}
This is an architecture question. I have Spring MVC web application that holds about a dozen collections that are rarely changed but that are often used in many-to-one relationships and for populating the drop-down selects that set the values of those properties. (For example: country, region, status types, etc).
In terms of performance and memory use, how should the app make these collections available?
At the moment I have a singleton wrapper class like the following:
#Component("collectionWrapper")
public class CollectionWrapper {
Map<Integer, Country> countries;
Map<Integer, User> users;
Map<Integer, Office> offices;
Map<Integer, Status> statuses
DAOService daoService;
public CollectionWrapper() {}
#Autowired(required=true)
public CollectionWrapper(DAOService daoService) {
this.daoService=daoService;
loadCountriesFromDao();
loadUsersFromDao();
loadOfficesFromDao();
loadStatusesFromDao();
}
public void loadCountriesFromDao() {
countries=daoService.getCountries();
}
// etc...
}
In the rare cases that an item in one of the collections is changed, the controller responsible for making the change calls collectionWrapper.loadCountriesFromDao(), for example.
Finally, the main objects that the app deals with have properties that map to these "reference objects", like so:
#Entity
public class Event {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id", nullable = false)
private Integer id;
#ManyToOne
#JoinColumn
private Office office;
etc...
}
So basically I'm wondering if this is the right way to be doing this. It is convenient to simply inject the collectionWrapper into my controllers and views, but I'm not sure how efficient it is on a lower level or if I'm missing something fundamental.
Thanks for sharing your experience!
I am trying to use a projection to pull in data from an entity an some relations it has. However. The constructor on the projection takes three arguments; a set, integer and another integer. This all works fine if I don't have the set in there as an argument, but as soon as I add the set, I start getting SQL syntax query errors.
Here is an example of what I'm working with...
#Entity
public class Resource {
private Long id;
private String name;
private String path;
#ManyToOne
#JoinColumn(name = "FK_RENDITION_ID")
private Rendition rendition;
}
#Entity
public class Document {
private Long id;
private Integer pageCount;
private String code;
}
#Entity
public class Rendition {
Long id;
#ManyToOne
#JoinColumn(name="FK_DOCUMENT_ID")
Document doc;
#OneToMany(mappedBy="rendition")
Set<Resource> resources;
}
public class Projection {
#QueryProjection
public Projection(Set<Resource> resources, Integer pageCount, String code) {
}
}
Here is the query like what I am using (not exactly the same as this is a simplified version of what I'm dealing with)....
QRendition rendition = QRendition.rendition;
Projection projection = from(rendition)
.where(rendition.document().id.eq(documentId)
.and(rendition.resources.isNotEmpty())
.limit(1)
.singleResult(
new QProjection(rendition.resources,
rendition.document().pageCount,
rendition.document().code));
This query works fine as long as my projection class does not have the rendition.resources in it. If I try and add that in, I start getting malformed SQL errors (it changes the output sql so that it starts with this.
select . as col_0_0_
So, I guess my main question here is how do I include a Set as an object in a projection? Is it possible, or am I just doing something wrong here?
Using collections in projections is unreliable in JPA. It is safer to join the collection and aggregate the results instead.
Querydsl can also be used for result aggregation http://www.querydsl.com/static/querydsl/3.2.0/reference/html/ch03s02.html#d0e1799
In your case something like this
QRendition rendition = QRendition.rendition;
Projection projection = from(rendition)
.innerJoin(rendition.document, document)
.innerJoin(rendition.resources, resource)
.where(document.id.eq(documentId))
.limit(1)
.transform(
groupBy(document.id).as(
new QProjection(set(resources),
document.pageCount,
document.code)));