I am building a Jersey Server with Maven Project and I have everything working fine except when I attempt to send a Request from a C# program I have that the user will be interacting with the array whose JSON appears as:
[{"Weight":0.0,"RFIDCode":0},{"Weight":55.5,"RFIDCode":1}]
When I send the code to the server I end up with an empty Java Array
My C# code is below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.IO;
using RestSharp;
namespace POSTJSONList
{
class Program
{
static void Main(string[] args)
{
List<ExampleMen> people = new List<ExampleMen>();
JsonSerializer ser = new JsonSerializer();
for (int i = 0; i < 5; i++)
{
ExampleMen person1 = new ExampleMen(i, i * 55.5);
people.Add(person1);
}
string json = JsonConvert.SerializeObject(people);
Console.WriteLine(json);
Console.ReadLine();
var client = new RestClient("http://localhost:9998");
var request = new RestRequest("/trash", Method.POST);
request.AddJsonBody(json);
client.ExecuteAsync(request, response => {
Console.WriteLine(response.Content);
});
Console.ReadLine();
}
}
}
My Java Code is below
#POST
#Produces("application/json")
#Consumes(MediaType.APPLICATION_JSON)
//#Param recycleList a list of all of the data that we have collected
public String createtrash_records(trashpickup_type trashList[]){
System.out.println("Im Here Guys!!!!");
// TODO update this to take the information we pass through to it and create individual objects based on it.
// TODO modify to return success code
billing billSystem = billing.getInstance();
systemTotalsTrash sysTotalsTrashSystem = systemTotalsTrash.getInstance();
int i = 1;
for(trashpickup_type alpha : trashList)
{
System.out.println(alpha.getRFIDCode() + alpha.getWeight());
i++;
/*try {
billSystem.updateBillingRecord(rec.getUserName(), 0, rec.getWeight());
sysTotalsTrashSystem.updateSystemTotals(rec.getWeight());
getDao().createIfNotExists(rec);
} catch (SQLException e) {
e.printStackTrace();
}
*/
}
return "It worked";
}
The Model Code (that which the JSON is mapped to) is Here
package com.gallup.gethip.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
#XmlRootElement
#DatabaseTable(tableName="trash_records")
public class trashpickup_type {
#DatabaseField(columnName = "RFIDCode")
private int RFIDCode;
#DatabaseField(columnName = "Weight")
private double Weight;
#DatabaseField(columnName = "PickedUp")
private Date PickedUp;
public trashpickup_type()
{
}
public void setRFIDCode(int RFIDCode)
{
this.RFIDCode = RFIDCode;
}
public void setWeight(double Weight)
{
this.Weight = Weight;
}
public void setPickedUP(Date PickedUp)
{
this.PickedUp = PickedUp;
}
public double getWeight()
{
return Weight;
}
public double getRFIDCode()
{
return RFIDCode;
}
public Date getPickedUp()
{
return PickedUp;
}
}
Any Suggestions are appreciated. I will post more information upon request if needed.
You serialize the people list to json and then use request.AddJsonBody to add it to the request. But AddJsonBody will again serialize the argument to json, so you end up with a double serialized value which - on the server side - cannot be parsed into trashList[]. Therefore remove the client-side serialization code and simply write
request.AddJsonBody(people);
Related
I would ultimately like to make a HTTP request to the NCBI Entrez database to retrieve some accession numbers. I'm starting out small here, so I wanted to make a functional HTTP request, regardless of the endpoint. But no matter the endpoint I use, a Unknown Host Exception is thrown. Why?
I have included all of my code, but the problem only happens in the method getEntireSubject.
import java.net.*;
import java.io.*;
import java.util.Scanner;
public class Subject {
private String id;
private String sequence;
// Position on ref sequence where alignment with query begins, inclusive
private int start;
// Position on ref sequence where alignment with query ends, inclusive
private int end;
public Subject(String accessNum, int hitFrom, int hitTo, String seq) {
id = accessNum;
sequence = seq;
start = hitFrom;
end = hitTo;
getEntireSubject();
}
// Getters
public String getSequence() {
return sequence;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
// Fetches accession number from NCBI
private void getEntireSubject() {
try {
String link = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/einfo.fcgi";
link = "https://jsonplaceholder.typicode.com/posts/1";
InputStream response = new URL(link).openStream();
try (Scanner scanner = new Scanner(response)) {
String responseBody = scanner.useDelimiter("\\A").next();
System.out.println(responseBody);
}
} catch (Exception e) {
System.out.println(e);
}
}
}
I have this JSON file which I would like to use for my mobile application for my university project, however I'm having issues accessing the "fields" section of it and I'm not sure the best way to access it.
{"total_hits":47287,"max_score":11.854574,
"hits":[
{"_index":"f762ef22-e660-434f-9071-a10ea6691c27",
"_type":"item",
"_id":"513fceb375b8dbbc21000022",
"_score":11.854574,
"fields":{
"item_id":"513fceb375b8dbbc21000022",
"item_name":"Cheese, cheddar - 1 cup, diced",
"brand_name":"USDA",
"nf_calories":533.28,
"nf_total_fat":43.97,
"nf_cholesterol":130.68,
"nf_sodium":861.96,
"nf_serving_size_qty":1,
"nf_serving_size_unit":"serving"}},
{"_index":"f762ef22-e660-434f-9071-a10ea6691c27",
"_type":"item",
"_id":"513fceb375b8dbbc21000021",
"_score":11.800501,
"fields":{"item_id":"513fceb375b8dbbc21000021",
"item_name":"Cheese, cheddar - 1 cup, melted",
"brand_name":"USDA",
"nf_calories":985.76,
"nf_total_fat":81.28,
"nf_cholesterol":241.56,
"nf_sodium":1593.32,
"nf_serving_size_qty":1,
"nf_serving_size_unit":"serving"}}, ... etc.
I can access the _Score value in the first section however, I am looking to access items like item_name, and nf_calories, however I'm not sure on the syntax. I believe I understand what I need to do, but I can't visualise it in my head.
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("hits");
List<NutritionModel> nutModelList = new ArrayList<>();
for(int i=0; i<parentArray.length(); i++) {
hitsObject = parentArray.getJSONObject(i);
NutritionModel nutModel = new NutritionModel();
nutModel.set_score(hitsObject.getDouble("_score"));
//Adding final object in the list
nutModelList.add(nutModel);
This is what I currently have in my ViewNutrition.java file.
public class NutritionModel {
private Double _score;
public Array getFieldarray() {
return fieldarray;
}
public void setFieldarray(Array fieldarray) {
this.fieldarray = fieldarray;
}
private Array fieldarray;
private String item_name;
private Double nf_calories;
private Double nf_total_fat;
private Double nf_protein;
private Double nf_cholesterol;
private Double nf_sodium;
private Double nf_serving_size_qty;
public Double get_score() {
return _score;
}
public void set_score(Double _score) {
this._score = _score;
}
public String getItem_name() {
return item_name;
}
public void setItem_name(String item_name) {
this.item_name = item_name;
}
public Double getNf_calories() {
return nf_calories;
}
public void setNf_calories(Double nf_calories) {
this.nf_calories = nf_calories;
}
public Double getNf_total_fat() {
return nf_total_fat;
}
public void setNf_total_fat(Double nf_total_fat) {
this.nf_total_fat = nf_total_fat;
}
public Double getNf_protein() {
return nf_protein;
}
public void setNf_protein(Double nf_protein) {
this.nf_protein = nf_protein;
}
public Double getNf_cholesterol() {
return nf_cholesterol;
}
public void setNf_cholesterol(Double nf_cholesterol) {
this.nf_cholesterol = nf_cholesterol;
}
public Double getNf_sodium() {
return nf_sodium;
}
public void setNf_sodium(Double nf_sodium) {
this.nf_sodium = nf_sodium;
}
public Double getNf_serving_size_qty() {
return nf_serving_size_qty;
}
public void setNf_serving_size_qty(Double nf_serving_size_qty) {
this.nf_serving_size_qty = nf_serving_size_qty;
}
}
This is what's currently in my custom class for using the JSON data.
I've tried cycling through a JSONObject with a for statement, searching for a JSONObject called "fields" however it still just returns null results. Been stuck for a couple of days now and really struggling, any help or direction would be appreciated! Thanks.
In order to access items like item_name, and nf_calories use need to go to access the inner array. So, how to do-
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("hits");
Suppose you need to access the elements(item_name etc.) of "hits" at index i then, you need to go to the inner JSONObject named "fields" and then you need to access the key named "item_name"
for that do-
for(int i=0;i<parentArray.length();i++) {
JSONObject obj1=parentArray.getJSONObject(i);
JSONObject obj2= obj1.getJSONObject("fields");
String item_name=obj2.getString("item_name");
}
Anyways even if you get confused in the explanation then for better JSON visualization access this website - http://jsonviewer.stack.hu/
The Field object isn't an Array it's an object. I suggest you create a FieldModel class and have the NutritionModel class contain an instance of the FieldModel class.
// In parser class
nutModel.setFields(hitsObject.getJSONObject("fields"));
// In NutritionModel class
public void setFields(JSONObject obj) {
this.fields.item_name = obj.getString("item_name");
// etc
}
Why does Integer field couldn't get the value that i sent. If i use Integer parameter by itself (like sending an ID) in WebMethod works fine.
Also the String field can get the value that i sent without any problem.
Here is the web service:
#WebService(serviceName = "testWS")
public class testWS {
#WebMethod(operationName = "Hello")
public Integer Hello(#WebParam(name = "testData") TEST testData) {
return testData.getINTPROP();
}
}
TEST type definition:
#XmlAccessorType(XmlAccessType.FIELD)
public class TEST {
private Integer INTPROP;//making public also didn't work
public Integer getINTPROP() {
return INTPROP;
}
public void setINTPROP(Integer INTPROP) {
this.INTPROP = INTPROP;
}
private String STRINGPROP;
public String getSTRINGPROP() {
return STRINGPROP;
}
public void setSTRINGPROP(String STRINGPROP) {
this.STRINGPROP = STRINGPROP;
}
}
C# consumer application:
...
test f = new test();
f.INTPROP = 123;
f.STRINGPROP = "abcdef";
var ff = ws.Hello(f);//returns 0
I hope i could explained my problem. thanks.
Try to change the setter to String.
public void setINTPROP(String INTPROP) {
this.INTPROPString = INTPROP;
Then change the String to an integrer with another function.
Return it as an integer, this should solve the problem.
Here is another aproach:
Add this function. Java should be able to handle this.
If the Variable you are passing is a integer, then the function you have will be used. If it is a String, Then this function will be called:
public String setINTPROP(String INTPROP) {
this.INTPROP = Integer.valueOf(INTPROP);
Ok. Marking field with #XmlSchemaType solved my problem.
#XmlSchemaType(name = "string")
public Integer INTPROP
I want to pass list of Object as the input to the web service.
I came to know we cannot achieve this using the built in Web Service task in SSIS. So I tried calling it through script task which uses C# Code.
I am able to call a Java Web Service(SOAP) through script Task.
I am able to test by passing simple parameters like string to the web service method.
Now I want to pass list of objects as parameter to the Web service method.
For testing purpose first I tried passing a object. The class in the c# client is as below
[Serializable]
public class Person
{
public string _PersonName;
public string _PersonNumber;
public string _Password;
public bool _isTrue;
public List<string> _configs;
public Person()
{
}
public Person(string PersonName, string PersonNumber, string Password, bool val)
{
_PersonName = PersonName;
_PersonNumber = PersonNumber;
_Password = Password;
_isTrue = val;
// _configs = config;
}
}
The corresponding proxy client class is as below
public partial class person {
private string _PersonNameField;
private string _PersonNumberField;
private string _PasswordField;
private bool _isTrueField;
private string[] _configsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string _PersonName {
get {
return this._PersonNameField;
}
set {
this._PersonNameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string _PersonNumber {
get {
return this._PersonNumberField;
}
set {
this._PersonNumberField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string _Password {
get {
return this._PasswordField;
}
set {
this._PasswordField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public bool _isTrue {
get {
return this._isTrueField;
}
set {
this._isTrueField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("_configs", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
public string[] _configs {
get {
return this._configsField;
}
set {
this._configsField = value;
}
}
}
The method in the proxy class is below
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="http://sample.xyz.abc.ext/", ResponseNamespace="http://sample.xyz.abc.ext/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("return", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string createPerson([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] person arg0) {
object[] results = this.Invoke("createJigBoard", new object[] {
arg0});
return ((string)(results[0]));
}
I am calling the method in the client as below
ServiceReference.TestService per = new ServiceReference.TestService();
var testList=new List<string>();
Person personOne = new Person("Manoj", "123456761", "Administrator", true,testList);
NetworkCredential myCred = new NetworkCredential("person", "person");
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri("http://pcblr********:80/*******/servlet/TestService"), "Basic", myCred);
StringWriter textWriter = new StringWriter();
XmlSerializer xmlSer = new XmlSerializer(typeof(Person));
xmlSer.Serialize(textWriter, personOne);
textWriter.Close();
per.createPerson(personOne);
I am getting the error
Argument 1: cannot convert from 'Client.Person' to 'Proxyclass.person' ******\ScriptMain.cs
The error message is correct. The service expects a ProxyClass.person but you are sending a Client.Person.
Instead of this line:
Person personOne = new Person("Manoj", "123456761", "Administrator", true,testList);
you should create a ProxyClass.person-object and map the parameters manually or use AutoMapper or similar.
You also need to change serialization from
XmlSerializer xmlSer = new XmlSerializer(typeof(Person));
to
XmlSerializer xmlSer = new XmlSerializer(typeof(ProxyClass.person));
I want to marshal/unmarshal 2 custom types. And the type 1 has a List. Marshalling works as expected - I see a separate element for every type2 element in the list, but when I try to unmarshal it this doesn't work.
Workflow
#XmlRootElement
public class Workflow {
private String userEmail;
private List<WorkflowStep> steps = new ArrayList<WorkflowStep>(5);
//required by jaxb
public Workflow() {
}
public void setSteps(List<WorkflowStep> steps) {
this.steps = steps;
}
public List<WorkflowStep> getSteps() {
//do a defensive copy
return new ArrayList<WorkflowStep>(steps);
}
public void setUserEmail(String email) {
userEmail = email;
}
public String getUserEmail() {
return userEmail;
}
}
WorkflowStep
#XmlRootElement
public class WorkflowStep {
private int cpu = 1;
private int mem = 1000;
private Map<String, String> parameters = Collections.emptyMap();
public WorkflowStep() {
}
public void setCpu(int numCores) {
cpu = numCores;
}
public int getCpu() {
return cpu;
}
public void setMem(int mb) {
mem = mb;
}
public int getMem() {
return mem;
}
}
Here is an example output if I access the web service from a browser:
<workflow>
<steps>
<cpu>1</cpu>
<inputId>237</inputId>
<mem>1000</mem>
<parameters/>
<status>NOT-YET-STARTED</status>
<stepId>1509</stepId>
<submoduleId>0</submoduleId>
<workflowId>797</workflowId>
</steps>
<steps>
<cpu>1</cpu>
<inputId>364</inputId>
<mem>1000</mem>
<parameters/>
<status>NOT-YET-STARTED</status>
<stepId>1510</stepId>
<submoduleId>3</submoduleId>
<workflowId>797</workflowId>
</steps>
<userEmail>foo#bar.com</userEmail>
<workflowId>797</workflowId>
<workflowName>test-name</workflowName>
</workflow>
WorkflowStep is marshalled/unmarshalled successfully but a List cannot be unmarshalled why is that? Nor the application server, nor the REST client receive any errors or exceptions, the client just ignores the list of WorkflowSteps? From the above example output I'd expect that every element would be converted into an object of type WorkflowStep and then will automatically be added to the List?
The problem is with this method:
public List<WorkflowStep> getSteps() {
//do a defensive copy
return new ArrayList<WorkflowStep>(steps);
}
Your JAXB implementation checks if there is already a List for this method, and if there is it uses it. The List you are returning is not held by the object you are unmarshalling, so after the unmarshal operation the List is lost.
Option #1 - Change the getSteps() Method
public List<WorkflowStep> getSteps() {
//don't do a defensive copy
return steps;
}
Option #2 - Use Field Access
You could change this your specify that JAXB should use field access.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Workflow {
...
}
For more information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html