the external web service returns me a Json file of the form
{"forecasts":[{"period_end":"2021-01-15T01:00:00.0000000Z","period":"PT30M","ghi90":0,"ghi":0,"ghi10":0},{"period_end":"2021-01-15T01:30:00.0000000Z","period":"PT30M","ghi90":0,"ghi":0,"ghi10":0},{"period_end":"2021-01-15T02:00:00.0000000Z","period":"PT30M","ghi90":0,"ghi":0,"ghi10":0}]}
Using RestRespone a transform an json element
RestResponse resp = rest.get(url)
resp.json instanceof JsonElement
How can I create a domain object from the Json element variable, knowing that my wrapper class is
class ForecastGhi {
static constraints = {
}
private ArrayList<IrradianciaGlobalHorizontal> forecast
ArrayList<IrradianciaGlobalHorizontal> getForecast() {
return forecast
}
void setForecast(ArrayList<IrradianciaGlobalHorizontal> forecast) {
this.forecast = forecast
}
}
and de persist domain class is
class IrradianciaGlobalHorizontal {
static constraints = {
}
#JsonProperty("all")
private def period_end
private def period
private def ghi90
private def ghi
private def ghi10
def getGhi() {
this.ghi
}
void setGhi(int ghi) {
this.ghi = ghi
}
def getGhi90() {
this.ghi90
}
void setGhi90(int ghi90) {
this.ghi90 = ghi90
}
def getGhi10() {
this.ghi10
}
void setGhi10(int ghi10) {
this.ghi10 = ghi10
}
def getPeriod_end() {
this.period_end
}
void setPeriod_end(Date period_end) {
this.period_end = period_end
}
def getPeriod() {
this.period
}
void setPeriod(String period) {
this.period = period
}
}
Help please; thanks a lot
This is an issue with your API implementation; The endpoint changed the domain field names &/or domain name. This will cause issues with bringing said data back in.
Either that or front-end is not matching the API docs for the endpoint.
Field names/domain names should match the domain/resource unless you are going for a level of obfuscation and then accept that you are going to need a middle layer to act as a translater (ie EDI).
You want output to be able to be read as input by the same endpoint by merely changing the request method.
My suggestion (easiest solution): change original endpoint to match domain/resource field names
If you have the opportunity to use Jackson library, you can do this:
ForecastGhi request = objectMapper.readValue(jsonAsText, ForecastGhi.class);
Create an objectMapper and configure to fail in case of unknown properties (just in case)
private String getJsonAsTextFromRest() {
String message = " {\"forecasts\":[{\"period_end\":\"2021-01-15T01:00:00.0000000Z\",\"period\":\"PT30M\",\"ghi90\":0,\"ghi\":0,\"ghi10\":0},{\"period_end\":\"2021-01-15T01:30:00.0000000Z\",\"period\":\"PT31M\",\"ghi90\":0,\"ghi\":0,\"ghi10\":0},{\"period_end\":\"2021-01-15T02:00:00.0000000Z\",\"period\":\"PT32M\",\"ghi90\":0,\"ghi\":0,\"ghi10\":0}]}";
return message;
}
#Override
public void run(String... arg0) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
String jsonAsText = getJsonAsTextFromRest();
ForecastGhi request = objectMapper.readValue(jsonAsText, ForecastGhi.class);
request.getForecast().stream().forEach(it -> System.out.println(it.getPeriod() + " " + it.getGhi()));
}
public class IrradianciaGlobalHorizontal {
private Date period_end;
private String period;
private int ghi90;
private int ghi;
private int ghi10;
public int getGhi() {
return this.ghi;
}
public void setGhi(int ghi) {
this.ghi = ghi;
}
public int getGhi90() {
return this.ghi90;
}
public void setGhi90(int ghi90) {
this.ghi90 = ghi90;
}
public int getGhi10() {
return this.ghi10;
}
void setGhi10(int ghi10) {
this.ghi10 = ghi10;
}
public Date getPeriod_end() {
return this.period_end;
}
public void setPeriod_end(Date period_end) {
this.period_end = period_end;
}
public String getPeriod() {
return this.period;
}
public void setPeriod(String period) {
this.period = period;
}
}
ForecastGhi class.
import com.fasterxml.jackson.annotation.JsonProperty;
public class ForecastGhi {
private ArrayList<IrradianciaGlobalHorizontal> forecast;
#JsonProperty("forecasts")//It must be the same as the json property
public ArrayList<IrradianciaGlobalHorizontal> getForecast() {
return forecast;
}
#JsonProperty("forecasts")
public void setForecast(ArrayList<IrradianciaGlobalHorizontal> forecast) {
this.forecast = forecast;
}
}
Results:
PT30M 0
PT31M 0
PT32M 0
Dependencies Gradle:
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1'
Or
Dependencies Maven:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.1</version>
</dependency>
Note: in your json example you use forecasts, but your java property name is forecast. In that case its necessary to decorate the property with #JsonProperty("forecasts"). If you dont do it, you get an error like this com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "forecasts"
Related
Hello Team,
I recently tried reading contents from application.yml file in a Spring Boot project (Version 2.3.4).
Initially, all the properties from yml file were getting read as null.
After cleaning and rebuilding project several times, I could read all the properties except the List of user defined class object (List<LogComponents> in below class) which is still getting read as null.
I tried all the possible solutions but nothing worked for me.
Could you please check and help me in understanding what I have missed in below code because of which the value for List<LogComponent> logComponents is still getting read as null from yml file?
Thanking you in anticipation!
Configuration Java Class
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties
public class TestAPIConfiguration {
private String eventCache;
private String diskBasedCache;
private List<String> sendAllSMSto;
private List<String> sendAllEmailsto;
//This property is getting read as null even if
//value for this property is present in yml file.
private List<LogComponent> logComponents;
#NotNull
private String selfURIPrefix;
#NotNull
private String investURIPrefix;
#NotNull
private String ifaURIPrefix;
private String apiEnv;
private final Joiner joiner = Joiner.on( "," ).skipNulls();
private static final Logger LOGGER = LoggerFactory.getLogger(TestAPIConfiguration.class);
#PostConstruct
public void setSystemProperties()
{
try
{
System.setProperty(SystemConstants.EVENT_CACHE_PATH, eventCache);
System.setProperty(SystemConstants.DISK_BASED_CACHE_PATH, diskBasedCache);
System.setProperty(SystemConstants.REQUEST_LOGGING_FIELDS,
JSONUtils.getObjectMapper().writeValueAsString(logComponents));
System.setProperty(SystemConstants.ENVIRONMENT_IDENTIFIER, apiEnv);
System.setProperty(INVEST_URI_PREFIX, investURIPrefix);
System.setProperty(IFA_URI_PREFIX, ifaURIPrefix);
if(sendAllSMSto != null)
System.setProperty(SEND_ALL_SMS_TO, joiner.join(sendAllSMSto));
if(sendAllEmailsto != null)
System.setProperty(SystemConstants.SEND_ALL_EMAILS_TO, joiner.join(sendAllEmailsto));
}
catch(Exception se)
{
LOGGER.error("Error in Configuration Setup: {}", se.getLocalizedMessage());
}
}
public String getEventCache() {
return eventCache;
}
public void setEventCache(String eventCache) {
this.eventCache = eventCache;
}
public String getDiskBasedCache() {
return diskBasedCache;
}
public void setDiskBasedCache(String diskBasedCache) {
this.diskBasedCache = diskBasedCache;
}
public List getSendAllSMSto() {
return sendAllSMSto;
}
public void setSendAllSMSto(List<String> sendAllSMSto) {
this.sendAllSMSto = sendAllSMSto;
}
public List getSendAllEmailsto() {
return sendAllEmailsto;
}
public void setSendAllEmailsto(List<String> sendAllEmailsto) {
this.sendAllEmailsto = sendAllEmailsto;
}
public List getRequestLoggingFields() {
return logComponents;
}
public void setRequestLoggingFields(List<LogComponent> requestLoggingFields) {
this.logComponents = requestLoggingFields;
}
public String getSelfURIPrefix() {
return selfURIPrefix;
}
public void setSelfURIPrefix(String selfURIPrefix) {
this.selfURIPrefix = selfURIPrefix;
}
public String getInvestURIPrefix() {
return investURIPrefix;
}
public void setInvestURIPrefix(String investURIPrefix) {
this.investURIPrefix = investURIPrefix;
}
public String getIfaURIPrefix() {
return ifaURIPrefix;
}
public void setIfaURIPrefix(String ifaURIPrefix) {
this.ifaURIPrefix = ifaURIPrefix;
}
public String getApiEnv() {
return apiEnv;
}
public void setApiEnv(String apiEnv) {
this.apiEnv = apiEnv;
}
}
LogComponent Java Class
#Component
public class LogComponent {
#NotNull
private String headerName;
#NotNull
private String sessionKey;
#NotNull
private String logPrintKey;
public String getHeaderName() {
return headerName;
}
public String getSessionKey() {
return sessionKey;
}
public String getLogPrintKey() {
return logPrintKey;
}
}
application.yml File
debug: true
server:
port: 8080
apiEnv: UAT
selfURIPrefix: "https://testurl.localhost.net"
investURIPrefix: "https://testurl.mediaserver.net"
ifaURIPrefix: "https://testurl.secondaryserver.net"
sendAllSMSto:
- "0000000000"
sendAllEmailsto:
- "abc#testmail.com"
eventCache: "C:\\Users\\username\\project\\devnull\\eventcachepurchase.mdb"
diskBasedCache: "C:\\Users\\username\\project\\devnull\\cache.mdb"
logComponents:
- headerName: X-RT-REQUEST-TRACKER
sessionKey: NOT AVAILABLE
logPrintKey: REQUEST-TRACKER
- headerName: X-RT-INX-DWD
sessionKey: IFX-PDR
logPrintKey: PDR_NO
- headerName: X-RT-IFA-ARN
sessionKey: IRX-AXRN
logPrintKey: AXR-CDODEEE
Finally, I found the solution.
I had not created setter methods inside the LogComponent class because of which the values were not getting assigned to the variables.
After adding the setters for all the fields, this issue has been resolved.
I am trying to generate a very simple code with Byte Buddy.
I have a POJO class where some fields are annotated with #SecureAttribute, For such fields I would like to override getter implementation and redirect the call to a SecurityService.getSecureValue() implementation.
Original class:
public class Properties {
#SecureAttribute
protected String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Desired Proxy:
public class PropertiesProxy {
private SecurityService securityService;
public void setSecurityService(SecurityService var1) {
this.securityService = var1;
}
public SecurityService getSecurityService() {
return this.securityService;
}
#Override
public String getPassword() {
return securityService.getSecureValue(password);
}
}
Emitting a field was easy but overriding a method becomes complicated. I have found a number of samples relative to my task which I try to apply but do not seem to get the required result.
So my major question is: how do I trace and debug the code generator? First thing I've learned was to print the class to file:
DynamicType.Unloaded<?> unloadedType = byteBuddy.make();
unloadedType.saveIn(new File("d:/temp/bytebuddy"));
This gives me an output where the extra field was added but not a glance of the getter override (disassembled from .class file):
public class PropertiesImpl$ByteBuddy$OLlyZYNY extends PropertiesImpl {
private SecurityService securityService;
public void setSecurityService(SecurityService var1) {
this.securityService = var1;
}
public SecurityService getSecurityService() {
return this.securityService;
}
public PropertiesImpl$ByteBuddy$OLlyZYNY() {
}
}
Here I do not exactly understand how to look for the error. Does it mean that I used totally wrong method implementation and Byte Buddy simply skipped it? Or am I wrong with ElementMatchers? Is there some trace or whatever that will give me a clue how to fix my code?
Current implementation:
private Class<?> wrapProperties() throws IOException {
DynamicType.Builder<?> byteBuddy = new ByteBuddy()
.subclass(PropertiesImpl.class)
.defineProperty("securityService", SecurityService.class);
Arrays.stream(PropertiesImpl.class.getDeclaredFields())
.filter(item -> item.getAnnotation(SecureAttribute.class) != null)
.forEach(item -> byteBuddy
.method(ElementMatchers.named(getGetterBeanName(item)))
.intercept(new GetterWrapperImplementation(item)));
DynamicType.Unloaded<?> unloadedType = byteBuddy.make();
unloadedType.saveIn(new File("d:/temp/bytebuddy"));
Class<?> wrapperClass = unloadedType.load(PropertiesImpl.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
return wrapperClass;
}
public static class GetterWrapperImplementation implements Implementation {
public static final TypeDescription SS_TYPE;
public static final MethodDescription SS_GET_SECURE_VALUE;
private final Field filed;
static {
try {
SS_TYPE = new TypeDescription.ForLoadedType(SecurityService.class);
SS_GET_SECURE_VALUE = new MethodDescription.ForLoadedMethod(SecurityService.class.getDeclaredMethod("getSecureValue", String.class));
}
catch (final NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
}
public GetterWrapperImplementation(Field filed) {
this.filed = filed;
}
#Override
public InstrumentedType prepare(final InstrumentedType instrumentedType) {
return instrumentedType;
}
#Override
public ByteCodeAppender appender(final Target implementationTarget) {
final TypeDescription thisType = implementationTarget.getInstrumentedType();
return new ByteCodeAppender.Simple(Arrays.asList(
TypeCreation.of(SS_TYPE),
// get securityService field
MethodVariableAccess.loadThis(),
FieldAccess.forField(thisType.getDeclaredFields()
.filter(ElementMatchers.named("securityService"))
.getOnly()
).read(),
// get secure field
MethodVariableAccess.loadThis(),
FieldAccess.forField(thisType.getDeclaredFields()
.filter(ElementMatchers.named(filed.getName()))
.getOnly()
).read(),
MethodInvocation.invoke(SS_GET_SECURE_VALUE),
MethodReturn.of(TypeDescription.STRING)
));
}
}
What I know for the fact is that breakpoints inside ByteCodeAppender appender(final Target implementationTarget) do not get hit, but again not sure how to interpret this.
Thanks.
The Byte Buddy DSL is immutable. This means that you always have to call:
builder = builder.method(...).intercept(...);
Your forEach does not do what you expect for this reason.
As for your implementation, you can just use MethodCall on a field and define the other field as an argument.
I have two classes as shown below. I need to use these two classes to extract few things.
public final class ProcessMetadata {
private final String clientId;
private final String deviceId;
// .. lot of other fields here
// getters here
}
public final class ProcMetadata {
private final String deviceId;
private final Schema schema;
// .. lot of other fields here
}
Now I have below code where I am iterating above two classes and extracting schema given a clientId.
public Optional<Schema> getSchema(final String clientId) {
for (ProcessMetadata metadata1 : processMetadataList) {
if (metadata1.getClientId().equalsIgnoreCase(clientId)) {
String deviceId = metadata1.getDeviceId();
for (ProcMetadata metadata2 : procMetadataList) {
if (metadata2.getDeviceId().equalsIgnoreCase(deviceId)) {
return Optional.of(metadata2.getSchema());
}
}
}
}
return Optional.absent();
}
Is there any better way of getting what I need by iterating those two above classes in couple of lines instead of what I have? I am using Java 7.
You're doing a quadratic* search operation, which is inneficient. You can do this operation in constant time by first creating (in linear time) a mapping from id->object for each list. This would look something like this:
// do this once, in the constructor or wherever you create these lists
// even better discard the lists and use the mappings everywhere
Map<String, ProcessMetadata> processMetadataByClientId = new HashMap<>();
for (ProcessMetadata process : processMetadataList) {
processMetadataByClientId.put(process.getClientId(), process);
}
Map<String, ProcMetadata> procMetadataByDeviceId = new HashMap<>();
for (ProcMetadata metadata2 : procMetadataList) {
procMetadataByDeviceId.put(proc.getDeviceId(), proc);
}
Then your lookup simply becomes:
public Optional<Schema> getSchema(String clientId) {
ProcessMetadata process = processMetadataByClientId.get(clientId);
if (process != null) {
ProcMetadata proc = procMetadataByDeviceId.get(process.getDeviceId());
if (proc != null) {
return Optional.of(proc.getSchema());
}
}
return Optional.absent();
}
In Java 8 you could write it like this:
public Optional<Schema> getSchema(String clientId) {
return Optional.fromNullable(processMetadataByClientId.get(clientId))
.map(p -> procMetadataByDeviceId.get(p.getDeviceId()))
.map(p -> p.getSchema());
}
* In practice your algorithm is linear assuming client IDs are unique, but it's still technically O(n^2) because you potentially touch every element of the proc list for every element of the process list. A slight tweak to your algorithm can guarentee linear time (again assuming unique IDs):
public Optional<Schema> getSchema(final String clientId) {
for (ProcessMetadata metadata1 : processMetadataList) {
if (metadata1.getClientId().equalsIgnoreCase(clientId)) {
String deviceId = metadata1.getDeviceId();
for (ProcMetadata metadata2 : procMetadataList) {
if (metadata2.getDeviceId().equalsIgnoreCase(deviceId)) {
return Optional.of(metadata2.getSchema());
}
}
// adding a break here ensures the search doesn't become quadratic
break;
}
}
return Optional.absent();
}
Though of course using maps ensures constant-time, which is far better.
I wondered what could be done with Guava, and accidentally wrote this hot mess.
import static com.google.common.collect.Iterables.tryFind
public Optional<Schema> getSchema(final String clientId) {
Optional<String> deviceId = findDeviceIdByClientId(clientId);
return deviceId.isPresent() ? findSchemaByDeviceId(deviceId.get()) : Optional.absent();
}
public Optional<String> findDeviceIdByClientId(String clientId) {
return tryFind(processMetadataList, new ClientIdPredicate(clientId))
.transform(new Function<ProcessMetadata, String>() {
String apply(ProcessMetadata processMetadata) {
return processMetadata.getDeviceId();
}
});
}
public Optional<Schema> findSchemaByDeviceId(String deviceId) {
return tryFind(procMetadataList, new DeviceIdPredicate(deviceId.get())
.transform(new Function<ProcMetadata, Schema>() {
Schema apply(ProcMetadata procMetadata) {
return processMetadata.getSchema();
}
});
}
class DeviceIdPredicate implements Predicate<ProcMetadata> {
private String deviceId;
public DeviceIdPredicate(String deviceId) {
this.deviceId = deviceId;
}
#Override
public boolean apply(ProcMetadata metadata2) {
return metadata2.getDeviceId().equalsIgnoreCase(deviceId)
}
}
class ClientIdPredicate implements Predicate<ProcessMetadata> {
private String clientId;
public ClientIdPredicate(String clientId) {
this.clientId = clientId;
}
#Override
public boolean apply(ProcessMetadata metadata1) {
return metadata1.getClientId().equalsIgnoreCase(clientId);
}
}
Sorry.
Similar with Restful syntax in Jersey or other framework, I could fetch the variable in the Restful uri path like that:
#Path("/users/{username}")
public class UserResource {
#GET
#Produces("text/xml")
public String getUser(#PathParam("username") String userName) {
...
}
}
but in californium, the syntax is different, I try these codes but it is not correct:
class usersextends CoapResource {
public users() {
super("users/{username}");
}
#Override
public void handleGET(CoapExchange exchange) {
exchange.respond("The username is "+ ???????);
}
}
How could I use the same function as first piece of code did? Another thing is where I can find official document introduce the API? I just saw the source code and try to find the solution now.
Create your own MessageDeliverer and change findResource method:
public class MyMessageDeliverer implements MessageDeliverer {
private final Resource root;
public MyMessageDeliverer(Resource root) {
this.root = root;
}
/* You can use implementation of methods from ServerMessageDeliverer */
#Override
public void deliverRequest(Exchange exchange) {
}
#Override
public void deliverResponse(Exchange exchange, Response response) {
}
/* method returns last known Resource instead of null*/
private Resource findResource(List<String> list) {
LinkedList<String> path = new LinkedList<String>(list);
Resource current = root;
Resource last = null;
while (!path.isEmpty() && current != null) {
last = current;
String name = path.removeFirst();
current = current.getChild(name);
}
if (current == null) {
return last;
}
return current;
}
}
Use your MessageDeliverer:
server = new CoapServer();
server.setMessageDeliverer(new MyMessageDeliverer(server.getRoot()));
Add your Resource to server:
server.add(new Users());
Request /users/{username} will be delivered to your Users resource. Fetch the variable from request URI:
public class Users extends CoapResource {
public Users() {
super("users");
}
public void handleGet(CoapExchange exchange) {
List<String> uri = exchange.getRequestOptions().getUriPath();
uri.remove("users");
String username = uri.remove(0);
//for query params:
Map<String, String> params = new HashMap<String, String>();
for (String p : exchange.getRequestOptions().getUriQuery()) {
String[] parts = p.split("=");
params.put(parts[0], parts[1]);
}
String param = params.get("param");
}
}
I am trying to pull data from class in another class and populate a JPanel with the data, but it is not working for some reason.
Here is the full restConnector class where I pull the JSON data.
As far as I know this works fine.
public class restConnector {
private static final Logger LOGGER = LoggerFactory.getLogger(restConnector.class);
private static final restConnector INSTANCE = new restConnector();
public static restConnector getInstance() {
return restConnector.INSTANCE;
}
private restConnector(){
}
private static String user = "ss";
private static String pwd = "ee
public static String encode(String user, String pwd) {
final String credentials = user+":"+pwd;
BASE64Encoder encoder = new sun.misc.BASE64Encoder();
return encoder.encode(credentials.getBytes());
}
//Open REST connection
public static void init() {
restConnector.LOGGER.info("Starting REST connection...");
try {
Client client = Client.create();
client.addFilter(new LoggingFilter(System.out));
WebResource webResource = client.resource("https://somewebpage.com/
String url = "activepersonal";
ClientResponse response = webResource
.path("api/alerts/")
.queryParam("filter", ""+url)
.header("Authorization", "Basic "+encode(user, pwd))
.header("x-api-version", "1")
.accept("Application/json")
.get(ClientResponse.class);
if (response.getStatus() != 200) {
}else{
restConnector.LOGGER.info("REST connection STARTED.");
}
String output = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyNameStrategy());
try {
List<Alert> alert = mapper.readValue(output, new TypeReference<List<Alert>>(){});
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
}
}
However, when I try to pull the data in another class it gives me just null values from the system.out.print inside refreshData() method. Here is the code that is supposed to print the data
public class Application{
Alert alerts = new Alert();
public Application() {
refreshData();
}
private void initComponents() {
restConnector.init();
refreshData();
}
private void refreshData() {
System.out.println("appalertList: "+alerts.getComponentAt(0));
}
}
Here is my Alert class
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(Include.NON_EMPTY)
public class Alert {
private int pasID;
private String status;
private boolean shared;
private String header;
private String desc;
public int getPasID() {
return pasID;
}
public void setPasID(int pasID) {
this.pasID = pasID;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public boolean isShared() {
return shared;
}
public void setShared(boolean shared) {
this.shared = shared;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\n***** Alert Details *****\n");
sb.append("PasID="+getPasID()+"\n");
sb.append("Status="+getStatus()+"\n");
sb.append("Shared="+isShared()+"\n");
sb.append("Header="+getHeader()+"\n");
sb.append("Description="+getDesc()+"\n");
sb.append("*****************************");
return sb.toString();
}
public String getComponentAt(int i) {
return toString();
}
}
I'm kind a lost with this and been stuck here for a couple of days already so all help would be really appreciated. Thanks for the help in advance.
Edit: Formatted the code a bit and removed the NullPointerException as it was not happening anymore.
As stated in comments:
Me: In your first bit of code you have this try { List<Alert> alert.., but you do absolutely nothing with the newly declared alert List<Alert>. It this where the data is supposed to be coming from?
OP: I'm under the impression that that bit of code is the one that pushes the JSON Array to the Alert.class. Is there something I'm missing there?
Me: And what makes you think it does that? All it does is read the json, and the Alert.class argument is the class type argument, so the mapper know the results should be mapped to the Alert attributes when it creates the Alert objects. That's how doing List<Alert> is possible, because passing Alert.class decribes T in List<T>. The List<Alert> is what's returned from the reading, but you have to determine what to actually do with the list. And currently, you do absolutely nothing with it
You maybe want to change the class just a bit.
Now this is in no way a good design, just an example of how you can get it to work. I would take some time to sit and think about how you want the restConnector to be fully utilized
That being said, you can have a List<Alert> alerts; class member in the restConnector class. And have a getter for it
public class restConnector {
private List<Alert> alerts;
public List<Alert> getAlerts() {
return alerts;
}
...
}
Then when deserializing with the mapper, assign the value to private List<Alert> alerts. What you are doing is declaring a new locally scoped list. So instead of
try {
List<Alert> alert = mapper.readValue...
do this instead
try {
alerts = mapper.readValue
Now the class member is assigned a value. So in the Application class you can do something like
public class Application {
List<Alert> alerts;
restConnector connect;
public Application() {
initComponents();
}
private void initComponents() {
connector = restConnector.getInstance();
connector.init();
alerts = connector.getAlerts();
refreshData();
}
private void refreshData() {
StringBuilder sb = new StringBuilder();
for (Alert alert : alerts) {
sb.append(alert.toString()).append("\n");
}
System.out.println("appalertList: "+ sb.toString());
}
}
Now you have access to the Alerts in the list.
But let me reiterate: THIS IS A HORRIBLE DESIGN. For one you are limiting the init method to one single call, in which it is only able to obtain one and only one resource. What if the rest service needs to access a different resource? You have made the request set in stone, so you cant.
Take some time to think of some good OOP designs where the class can be used for different scenarios.