How to read a specific value from a JCoTable object - java

I successfully got the Table entries from a SAP system via RFC_GET_TABLE_ENTRIES. It works all fine and lists me all the rows of the table.
My problem right now is that I have no idea how to get a single value out. Usually I would go like codes [x][y] but that doesn't work because it is not a normal two-dimensional-array table but a JCOtable and I have no idea how that works.
The code is a little longer but this is the call itself.
JCoDestination destination = JCoDestinationManager.getDestination("mySAPSystem");
JCoFunction function = destination.getRepository().getFunction("RFC_GET_TABLE_ENTRIES");
if (function==null)
throw new RuntimeException("Function not found in SAP.");
function.getImportParameterList().setValue( "MAX_ENTRIES", 30);
function.getImportParameterList().setValue( "TABLE_NAME", "ZTEST_TABLE ");
JCoTable codes = function.getTableParameterList().getTable("ENTRIES");
codes.appendRow();
and this is the console output
System.out.println("RFC_GET_TABLE_ENTRIES");
for (int i = 0; i < 30; i++) {
codes.setRow(i);
System.out.println(codes.getString("WA"));
}

getString actually accepts indexes as well. If you want to retrieve values according to x and y you can do the following
codes.setRow(y);
String value = codes.getString(x); // It can also be getFloat, getInt, etc. depending on the data type,
// or getValue, which gives you an Object
It works similarly to codes[x][y] as if it's an array, but this is not commonly used.
In other cases, you may want to iterate through each single value in the row with JCoRecordFieldIterator.
JCoRecordFieldIterator itr = codes. getRecordFieldIterator();
while(itr.hasNextField()){
JCoRecordField field = itr.nextRecordField();
String value = field.getValue(); // Or getString, getFloat, etc.
// Whatever you want to do with the value
}

Related

JAVA sapjco3 Can't find data from returned table

I have a SAP RFC named ZRFC_BOM_005. After I exec the RFC function, I try to get field's value from the returned table, but it only shows field's name but no field's value. However, the function "printJCoTable(JCoTable jcoTable)" works fine with other RFC. I don't know what's wrong with it here.
This is my code:
Execute SAP RFC:
JCoFunction function = destination.getRepository().getFunction("ZRFC_BOM_005");
JCoParameterList input = function.getImportParameterList();
input.setValue("DATE_FROM", datefrom);
input.setValue("DATE_TO", dateto);
input.setValue("I_CAPID", i_capid);
input.setValue("I_MEHRS", i_mehrs);
input.setValue("I_MTNRV", i_mtnrv);
input.setValue("I_STLAN", i_stlan);
input.setValue("I_WERKS", i_werks);
if (function == null)
throw new RuntimeException("ZRFC_BOM_005 not found in SAP.");
try {
function.execute(destination);
} catch (AbapException e) {
System.out.println(e.toString());
}
JCoTable table = function.getTableParameterList().getTable("T_BOMITEM");
printJCoTable(table);
Use printJCoTable to print table's field and table's value:
public static List<List<String>> printJCoTable(JCoTable jcoTable) {
List<List<String>> listData = new ArrayList<List<String>>();
// header
// JCoRecordMeataData is the meta data of either a structure or a table.
// Each element describes a field of the structure or table.
JCoRecordMetaData tableMeta = jcoTable.getRecordMetaData();
for (int i = 0; i < tableMeta.getFieldCount(); i++) {
System.out.print(String.format("%s\t\t", tableMeta.getName(i)));
}
System.out.println(); // new line
// line items
for (int i = 0; i < jcoTable.getNumRows(); i++) {
// Sets the row pointer to the specified position(beginning from zero)
jcoTable.setRow(i);
// Each line is of type JCoStructure
List list = new ArrayList<>();
for (JCoField fld : jcoTable) {
list.add(fld.getValue());
System.out.print(String.format("%s\t", fld.getValue()));
}
listData.add(list);
System.out.println();
}
return listData;
}
But it turns out only field's name but no field's value.
PS:I'm sure that there are returned field's value exist with the same params i put, because i have checked it by another software which is link to SAP.
is it possible to be Timeout problem ? because when I exec this RFC, it takes about 10 mins to run.
Then how can I solve this?
As you commented that jcoTable.getNumRows() returns 0:
That means that the table is empty and the JCo exception error message is correct if you are trying access any content fields of this table.
So your RFC call returns this empty table which means that your input parameter values do not seem to contain the data which you are expecting. Check them once again.
I guess your DATE_FROM and DATE_TO parameters are set wrongly. Either put java.util.Date objects in there, or if dateto and datefrom have to be strings, then choose the date format yyyyMMdd or yyyy-MM-dd for their content, i.e. "20180319" or "2018-03-19" for today's date.
If it is not that easy, it also could be something with the EXTERNAL to INTERNAL representation conversion exit routines which are called and used by transaction SE37 automatically, but not if the RFC-enabled function module is called directly from external side. For more details on this and other issues in this area I recommend to study SAP note 206068.
You may check both scenarios with the ABAP debugger tool in order to see which input parameter values are really passed when your function module is called via SE37 compared to being called via your JCo program.

By using setters in model class Saved data is saved repeatedly?

By using setters and getters class, I am setting values to MusicDetailsObject(pojo class) when setting first value it is set, then setting second value it is set and also replacing first value and so on...... setting values using loop:
for(int k=0;k<songs.length();k++)
{
JSONObject songObject = songs.getJSONObject(k);
//mName.add(songObject.getString("name"));
mObject.setmName(songObject.getString("name"));
//mURL .add(songObject.getString("url"));
mObject.setmURL(songObject.getString("url"));
//mListId .add(songObject.getString("id"));
mObject.setmID(songObject.getString("id"));
mAlbumList.add(mObject);
}
first time setting values as
array1{id = 101
name = Jigarthanda}
When setting value second time it showing like this:
array1{id = 102
name = Mundasupatti}, array1{id = 102
name = Mundasupatti}
so, please let me know how to set an individual value.
Thanks in advance.
The issue is that, inside the loop, you never create a new instance of mObject, so the only instance you have is getting reused.
for(int k=0;k<songs.length();k++){
JSONObject songObject = songs.getJSONObject(k);
mObject = new MyObject() // -> NOW you are assigning values to a different instance.
//mName.add(songObject.getString("name"));
mObject.setmName(songObject.getString("name"));
//mURL .add(songObject.getString("url"));
mObject.setmURL(songObject.getString("url"));
//mListId .add(songObject.getString("id"));
mObject.setmID(songObject.getString("id"));
mAlbumList.add(mObject);
}

Accessing returned object in Loop

I had a quick question, Right now I have a method that returns a populated DTO object, in another class I am calling that method, and then trying to get access to some of the values that are on the returned Object. I am having trouble figuring out what the syntax should be to accomplish this. It is returning "result". I am currently getting an error:
"Null pointer access: The variable result can only be null at this location"
The DTO that I am returning contains a List and I want to get access to one of the values on that list. Below is my code snippet. Thank you for your help!
for (Integer i = 0; i < array.size(); i++) {
// System.out.println(array.get(i));
GetAccountRewardSummaryRequest request = new GetAccountRewardSummaryRequest();
AccountRewardSummaryDTO result = null;
request.accountKey = new AccountIdDTO(array.get(i));
RewardServicesImpl rewardServicesImpl = new RewardServicesImpl();
rewardServicesImpl.getAccountRewardSummary(request);
// This will return an AccountRewardSummaryDTO, print out and see if it is returning properly
System.out.println(result.rewards.get(6));
// System.out.println(request.accountKey);
}
It's not clear from your question, but I suspect that this:
rewardServicesImpl.getAccountRewardSummary(request);
should be:
result = rewardServicesImpl.getAccountRewardSummary(request);
If you want to use the value returned from a method, you need to do something with it.
Your code would be clearer if you didn't declare the result variable until you needed it though - and there's no point in using Integer here instead of int. Additionally, unless you really can't reuse the service, you might as well create that once:
RewardServices service = new RewardServicesImpl();
for (int i = 0; i < array.size(); i++) {
GetAccountRewardSummaryRequest request = new GetAccountRewardSummaryRequest();
request.accountKey = new AccountIdDTO(array.get(i));
AccountRewardSummaryDTO result = service.getAccountRewardSummary(request);
System.out.println(result.rewards.get(6));
}
Also, as noted, the fact that your variable called array clearly isn't an array variable is confusing.

Using LiveCycle How can I create and populate a new row in a table with values from other fields with a button press?

Here is my current code, so far the button will create a new row in the table and it will reset the fields (AdditionalComments, CellLocation, and FailureSelection, which are all text fields), but it will not allow me to populate the original FailureRow or the new instance of FailureRow that is created:
field name="AddFailureButton" w="31.114mm" h="6mm">
event name="event__click" activity="click"
script contentType="application/x-javascript"
xfa.host.messageBox("Failure Recorded, Please Continue Filling Out the Form Until All Failures Have Been Recorded. Then Please Save and Submit the form.", "Continue/Save/Submit", 3);
this.resolveNode('failuretable.Table1._FailureRow').addInstance(1);
if (xfa.host.version < 8) {
xfa.form.recalculate(1);
}
//****need to set values of current FailureRow to be equal to CellLocation, FailureSelection, and AdditionalComments, THEN clear the values as written below*****
xfa.host.resetData("form1.page1.AdditionalComments");
xfa.host.resetData("form1.page1.CellLocation");
xfa.host.resetData("form1.page1.FailureSelection");
</script>
Try the following code:
var newRow = this.resolveNode('failuretable.Table1._FailureRow').addInstance(1);
newRow.CELL_NAME.rawValue = form1.page1.AdditionalComments.rawValue;
newRow.CELL_NAME.rawValue = form1.page1.CellLocation.rawValue;
newRow.CELL_NAME.rawValue = form1.page1.FailureSelection.rawValue;
Remember to replace CELL_NAME with a proper name.
btw. When you are referencing object in the script you can just use it's SOM expression failuretable.Table1._FailureRow instead of this.resolveNode('failuretable.Table1._FailureRow').

Nightmare Class - floats/strings

This is my class reponsible for new item entries, and from the start it has been a complete nightmare, I can't seem to resolve the issues I am facing which are:
setStock(float) in Item cannot be applied to ()
Item entry:
private void writeItemRecord()
{
// Check to see if we can connect to database table
if ( DataBaseHandler.makeConnectionToitemDB() == -1)
{
JOptionPane.showMessageDialog (frame, "Unable to connect to database table (Item)");
}
else // Ok, so first read data from the text fields
{
// Read data from form and store data
String Itemname = ItemnameTxtField.getText();
String Itemcode = ItemcodeTxtField.getText();
String Description = DescriptionTxtField.getText();
String Unitprice = UnitpriceTxtField.getText();
String Style = StyleTxtField.getText();
String Finish = FinishTxtField.getText();
String Stock = StockTxtField.getText();
// Convert priceStr to a float
Float fvar = Float.valueOf(Unitprice);
float price = fvar.floatValue();
Float svar = Float.valueOf(Stock);
float stock = svar.floatValue();
// Create a Item oject
Item Item = new Item();
// Set the attributes for the Item object
Item.setItemname (Itemname);
Item.setItemcode (Itemcode);
Item.setDescription (Description);
Item.setUnitprice (price);
Item.setStock(stock);
Item.setStyle(Style);
Item.setFinish(Finish);
// Write Item record. Method writeToItemTable() returns
// 0 of OK writing record, -1 if there is a problem. I store
// the returned value in a variable called error.
int error = DataBaseHandler.writeToItemTable(Item.getItemname(),
Item.getItemcode(),
Item.getDescription(),
Item.getUnitprice(),
Item.setStock(),
Item.setStyle(Style),
Item.setFinish(Finish),
Item.setSuppliercode(Suppliercode),
Item.setSuppliername(Suppliername),
Item.setAddress(Address)
);
// Check if there is a problem writing the record, in
// which case error will contain -1
if (error == -1)
{
JOptionPane.showMessageDialog (frame, "Problem writing record to Item Table");
}
// Clear the form - actual method is coded below
clearForm();
// Close database connection. Report an error message
// if there is a problem.
if ( DataBaseHandler.closeConnection() == -1 )
{
JOptionPane.showMessageDialog (frame, "Problem closing data base conection");
}
}
} // End
Any help is much appreciated!
And item extracts:
public void setStock(float StockIn)
{
Stock = StockIn;
}
public float getStock()
{
return Stock;
}
For starters, adhere to Java naming conventions. Nothing except class/interface names is allowed to use CamelCase. Use lowerCamelCase. As for your "problem", you wrote
Item.setStock(),
so obviously it's giving you the error. It is also giving you the exact line number of the error, something that would obviously have helped us to diagnose your problem.
Solution: use Item.getStock() (i suppose, it's hard to tell). Calling Item.setStock at that position (as an argument to a method call) is meaningless anyway, given that setStock is a void method.
Java compiler errors come with a line number - pay attention to it. This is your problem:
Item.setStock()
setStock() requires a parameter, you are trying to call it without one. Perhaps you meant getStock()? And I suspect that all the calls to set methods in the parameter list to writeToItemTable are also wrong, as those set methods will have void as return value, so you can't use them that way.
The setStock method looks like this:
public void setStock(float StockIn)
To call it, you need to pass a float as an argument. Somewhere in your code, you call the method, like this:
Item.setStock(),
The method needs to be called with the float argument, but instead it's called with none, hence you see a compilation error.
In this code:
int error = DataBaseHandler.writeToItemTable(Item.getItemname(),
Item.getItemcode(),
Item.getDescription(),
Item.getUnitprice(),
// Right here --> Item.setStock(),
Item.setStyle(Style),
Item.setFinish(Finish),
Item.setSuppliercode(Suppliercode),
Item.setSuppliername(Suppliername),
Item.setAddress(Address)
);
Notice that you're calling Item.setStock(), Item.setStyle(Style), etc. instead of Item.getStock(), Item.getStyle(), etc. This is probably the source of your problem - you're trying to call the setStock() method with no arguments, hence the error.
Hope this helps!
This line
// Create a Item oject
Item Item = new Item();
Is problematic. Not only is it bad style in Java to use uppercase names for variables, this particular instance results in a compile error. Also, you're calling setStock without a parameter. You need to fix that as well.
Here is your error:
int error = DataBaseHandler.writeToItemTable(Item.getItemname(),
Item.getItemcode(),
Item.getDescription(),
Item.getUnitprice(),
Item.setStock(), // <<< here! should be getStock()
Item.setStyle(Style),
Item.setFinish(Finish),
Item.setSuppliercode(Suppliercode),
Item.setSuppliername(Suppliername),
Item.setAddress(Address));
But again... consider naming/coding conventions.

Categories