How can I populate a list with data from a SQLite database in my Blackberry application? I can view the list, but I can see only one item which is the last item from my database table in the list. Below is the code:
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.database.Database;
import net.rim.device.api.database.DatabaseFactory;
import net.rim.device.api.database.Row;
import net.rim.device.api.database.Statement;
import net.rim.device.api.io.URI;
class ListFieldScreen extends MainScreen
{
Database d;
public ListFieldScreen()
{
final ObjectListField list = new ObjectListField();
try
{
URI myURI=URI.create("file:///SDCard/Databases/MyTestDatabase.db");
d=DatabaseFactory.open(myURI);
Statement st=d.createStatement("SELECT eng FROM English");
st.prepare();
net.rim.device.api.database.Cursor c=st.getCursor();
Row r;
while(c.next())
{
r=c.getRow();
String w=r.getString(0);
String[] t={w};
list.set(t);
add(list);
}
st.close();
d.close();
}
catch ( Exception e ) {
e.printStackTrace();
}
}
}
Try like this:
First declare as
public Vector tableVector;
public ObjectListField list;
and call this below code in separate method;
tableVector=new Vector();//Declare this before the method;
try
{
//Uri creation
Statement st=LoadingScreen.database.createStatement("YOUR Statement");
st.prepare();
Cursor c = st.getCursor();
Row r;
while(c.next())
{
r = c.getRow();
tableVector.addElement(r.getString(0));
}
st.execute();
st.close();
}
catch(Exception e)
{
//Exception;
}
After complete this method; show the data as...
String ar[]=new String[tableVector.size];
for(int i=0;i<tableVector.size;i++)
{
ar[i]=tableVector.elementAt(i).toString();
}
list.set(ar);
add(list);
I suppose you need to specify number of items you want to show in the list - I mean number of ites from db -
Related
I have created a method to dynamically build rest URI based on Bean properties, initially it was imperative then I have refactored it to functional style, it's my first time doing functional programming.
both imperative and functional are working as expected, but I am not happy by the functional readability, functional seams an over kill for this method or it could be because i am still a novice functional programmer!
How would you refactor this method to more clean functional way?
Or would you keep it Imperative?
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.lang.reflect.Method;
import org.springframework.beans.BeanUtils;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.util.UriComponentsBuilder;
public String functionalBuildRestUri() throws Exception {
final UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance().scheme("https")
.host("foo.com").path("/offers");
//here is the functional
List<PropertyDescriptor> propDescList = Arrays.asList(BeanUtils.getPropertyDescriptors(getClass()));
//this part is readable and precis, but to enable it had to add 4 methods
propDescList.stream().filter(notClassProp())
.filter(notNullPropValue())
.collect(Collectors.toMap(PropertyDescriptor::getName, propValue()))//conversion to map doesn't feel good to me how can I avoid it?
.forEach(buildRestParam(uriBuilder));
return uriBuilder.build().toUriString();
}
public String imperativeBuildRestUri() throws Exception {
final UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance().scheme("https")
.host("foo.com").path("/offers");
PropertyDescriptor[] propDescArray = BeanUtils.getPropertyDescriptors(getClass());
for (PropertyDescriptor propDesc : propDescArray) {
String propName = propDesc.getName();
if (!propName.equals("class")) {
Method getPropMethod = propDesc.getReadMethod();
Object propValue = getPropMethod.invoke(this);
if (propValue != null) {
if(propValue instanceof Date){
String dateStr = new SimpleDateFormat(DATE_FORMAT).format((Date)propValue);
uriBuilder.queryParam(propName, ":"+dateStr);
}else{
uriBuilder.queryParam(propName, propValue);
}
}
}
}
return uriBuilder.build().toUriString();
}
All Those methods has been added after functional refactoring
// I couldn't avoid being imperative here, how can we refactor it to more functional style
private BiConsumer<String, Object> buildRestParam(final UriComponentsBuilder uriBuilder) {
return (propName, propValue) -> {
if (propValue instanceof Date) {
String dateStr = new SimpleDateFormat(DATE_FORMAT).format((Date) propValue);
uriBuilder.queryParam(propName, ":" + dateStr);
} else {
uriBuilder.queryParam(propName, propValue);
}
};
}
private Predicate<? super PropertyDescriptor> notNullPropValue() {
return propDesc -> {
return propValue().apply(propDesc) != null;
};
}
private Predicate<? super PropertyDescriptor> notClassProp() {
return propDesc -> {
return !propDesc.getName().equals("class");
};
}
private Function<? super PropertyDescriptor, ? extends Object> propValue() {
return (propDesc) -> {
try {
return propDesc.getReadMethod().invoke(HotelOfferSearchCommand.this);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
};
}
Most of the verbosity of the new code has nothing to do with functional programming. You have refactored the code to put every lambda expression into a method of it’s own, which, of course, destroys one of the main advantages of lambda expressions, the compactness. Even if code is complex enough to justify the creation of a method, that method should perform actual work, then, you could use a method reference where a function is required.
The methods further suffer from an unnecessary (even discouraged, as being in a return type) use of wild cards. You also used the verbose syntax parameter -> { return expression; } where parameter -> expression would be possible.
There are other issues, like unnecessarily creating a distinct catch clause for each exception type, when all do the same or wrapping the array into a List before creating the Stream instead of streaming over the array directly or having code duplication, the last point applies to both, the imperative variant and the functional one.
You can just write:
public String functionalBuildRestUri() throws Exception {
final UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance()
.scheme("https").host("foo.com").path("/offers");
Function<PropertyDescriptor, Object> propValue = propDesc -> {
try { return propDesc.getReadMethod().invoke(HotelOfferSearchCommand.this); }
catch(ReflectiveOperationException e) { throw new RuntimeException(e); }
};
Arrays.stream(BeanUtils.getPropertyDescriptors(getClass()))
.filter(propDesc -> !propDesc.getName().equals("class"))
.filter(propDesc -> propValue.apply(propDesc) != null)
.forEach(propDesc -> {
Object value = propValue.apply(propDesc);
if (value instanceof Date)
value = ":"+new SimpleDateFormat(DATE_FORMAT).format(value);
uriBuilder.queryParam(propDesc.getName(), value);
});
return uriBuilder.build().toUriString();
}
without any extra method.
This might not be the best option, as there is indeed one flaw, the absence of a tuple or pair type to hold two values to be passed through the stream. By using Map.Entry as a stand-in, but not populating a Map, we can express the operation as
public String functionalBuildRestUri() throws Exception {
final UriComponentsBuilder uriBuilder = UriComponentsBuilder.newInstance()
.scheme("https").host("foo.com").path("/offers");
Function<PropertyDescriptor, Object> propValue = propDesc -> {
try { return propDesc.getReadMethod().invoke(HotelOfferSearchCommand.this); }
catch(ReflectiveOperationException e) { throw new RuntimeException(e); }
};
Arrays.stream(BeanUtils.getPropertyDescriptors(getClass()))
.filter(propDesc -> !propDesc.getName().equals("class"))
.map(propDesc -> new AbstractMap.SimpleImmutableEntry<>(
propDesc.getName(), propValue.apply(propDesc)))
.filter(entry -> entry.getValue() != null)
.forEach(entry -> {
Object value = entry.getKey();
if (value instanceof Date)
value = ":"+new SimpleDateFormat(DATE_FORMAT).format(value);
uriBuilder.queryParam(entry.getKey(), value);
});
return uriBuilder.build().toUriString();
}
or, alternatively
Arrays.stream(BeanUtils.getPropertyDescriptors(getClass()))
.filter(propDesc -> !propDesc.getName().equals("class"))
.map(propDesc -> new AbstractMap.SimpleImmutableEntry<>(
propDesc.getName(), propValue.apply(propDesc)))
.filter(entry -> entry.getValue() != null)
.map(e -> e.getValue() instanceof Date?
new AbstractMap.SimpleImmutableEntry<>(e.getKey(),
":"+new SimpleDateFormat(DATE_FORMAT).format(e.getValue())):
e)
.forEach(entry -> uriBuilder.queryParam(entry.getKey(), entry.getValue()));
With these two variants, the propValue function is evaluated only once per element instead of two times as in the first variant and your original code, where both, the check for null property value and the terminal operation evaluated it.
Note that there’s still room for improvement, e.g. there’s no reason to add the ":" after the format operation when you could make the colon a part of the format pattern string in the first place.
Whether this is an improvement over the loop, is something you have to decide yourself. Not every code has to be rewritten to a functional style. At least, as shown by the the examples above, it doesn’t have to be bigger than the imperative code…
I have created a program using CallableStatement and Cursors to fetch the records from a table named Student with names starting from 'A' with pl/sql procedures.The program is giving an SQLException: java.sql.SQLException: operation not allowed: Ordinal binding and Named binding cannot be combined!
please help me out to resolve this..
the procedure is:
create or replace procedure get_StudDetails(mycur out sys_refcursor,cond in varchar)
as
begin
open mycur for
select * from Student where stname like cond;
end;
/
the java program is:
import java.sql.*;
import oracle.jdbc.driver.*;
class CursorTest
{
public static void main(String s[])
{
try
{
Connection con=DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:orcl","rt","pwdd");
CallableStatement cs=con.prepareCall("{call get_StudDetails(?,?)}");
cs.getString(2+"A%");
cs.registerOutParameter(1,OracleTypes.CURSOR);
cs.execute();
System.out.println("procedure invoked");
ResultSet rs=(ResultSet)cs.getObject(1);
while(rs.next())
{
System.out.println(rs.getString(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3)+"\t"+rs.getString(4));
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Don't use getString but setString instead:
CallableStatement cs=con.prepareCall("{call get_StudDetails(?,?)}");
cs.registerOutParameter(1,OracleTypes.CURSOR);
cs.setString(2, "A%");
cs.execute();
I'm working with DynamoDB at the moment. I want to use a conditional write to update a record if that record has a date that is older than the new record date field.
Is there a way to compare DateTime types for conditional writes? Or is it currently only for integers, strings and streams?
Thanks.
Since you mentioned you are using ISO-8601 with the String datatype, it is easy to use the comparing operators (<, <=, etc.) in your conditional expression because of the lexicographical ordering described in this answer.
Here is a quick example where I used Java 8's time and ran it against DynamoDB Local:
import com.google.common.collect.ImmutableMap;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.services.dynamodbv2.util.Tables;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class DynamoDBStackoverflow {
public static final String TABLE_NAME = "exampleTable";
private static final String HASH_KEY = "hashAttributeName";
public static void main(String[] args) {
AWSCredentials awsCredentials = new BasicAWSCredentials("key", "secret");
AmazonDynamoDB client = new AmazonDynamoDBClient(awsCredentials);
client.setEndpoint("http://localhost:4000");
DynamoDB dynamoDB = new DynamoDB(client);
if (Tables.doesTableExist(client, TABLE_NAME)) {
client.deleteTable(TABLE_NAME);
}
final CreateTableRequest createTableRequest = new CreateTableRequest()
.withTableName(TABLE_NAME)
.withKeySchema(new KeySchemaElement(HASH_KEY, KeyType.HASH))
.withAttributeDefinitions(new AttributeDefinition(HASH_KEY, ScalarAttributeType.S))
.withProvisionedThroughput(new ProvisionedThroughput(15L, 15L));
final Table table = dynamoDB.createTable(createTableRequest);
final Instant now = Instant.now();
final Instant before = now.minus(10, ChronoUnit.MINUTES).truncatedTo(ChronoUnit.MINUTES);
final Instant after = now.plus(10, ChronoUnit.MINUTES);
System.out.println("Before: " + before.toString());
System.out.println("Now: " + now.toString());
System.out.println("After: " + after.toString());
table.putItem(new Item().withPrimaryKey(HASH_KEY, "1")
.withString("dateField", before.toString()));
table.putItem(new Item().withPrimaryKey(HASH_KEY, "2")
.withString("dateField", now.toString()));
System.out.println("put items");
table.scan().forEach(System.out::println);
UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
.withConditionExpression("dateField < :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
throw new RuntimeException();
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("expected conditional write with < to fail when they are equal");
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
.withConditionExpression("dateField < :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
throw new RuntimeException();
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("expected conditional write with < to fail when new is before");
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
.withConditionExpression("dateField <= :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("should not happen");
throw new RuntimeException();
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
.withConditionExpression("dateField <= :afterDate")
.withValueMap(ImmutableMap.of(":afterDate", after.toString()))
.withUpdateExpression("SET dateField = :afterDate");
try {
table.updateItem(updateItemSpec);
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("should not happen");
throw new RuntimeException();
}
System.out.println();
System.out.println("after all updates");
table.scan().forEach(System.out::println);
}
}
And the output:
Before: 2015-06-08T15:57:00Z
Now: 2015-06-08T16:07:08.893Z
After: 2015-06-08T16:17:08.893Z
put items
{ Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} }
{ Item: {hashAttributeName=2, dateField=2015-06-08T16:07:08.893Z} }
expected conditional write with < to fail when they are equal
expected conditional write with < to fail when new is before
after all updates
{ Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} }
{ Item: {hashAttributeName=2, dateField=2015-06-08T16:17:08.893Z} }
DynamoDB doesn't understand dates. If you save the date as long, ms/s since epoch, then you can use arithmetic <, >=, etc.
If you use a String presentation, then it all depends if you can find the right DynamoDB operator to query on two of them.
I personally use the former, thus doing it with calculus.
How to verify an attribute whether it present in table or not without using scan in dynamodb?
In my usecase, From client side, The customer request with their Customer_id for knowing the values of the product. In server side, have to check whether the entered customer_id already present in DynamoDB table or not. If not, have to make a new entry.
How can I implement this case without using SCAN operation to the table?
It sounds to me that you want to do a conditional PutItem on this table: put the item into the table if there is not another item with the same customer_id. This is easy enough to do because the customer_id is the hash key of the table. From the PutItem documentation:
Note
To prevent a new item from replacing an existing item, use a conditional put operation with ComparisonOperator set to NULL for the
primary key attribute, or attributes.
Here is a quick example I coded up using the Dynamo DB document API in the Java SDK and running against DynamoDB Local:
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Expected;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.services.dynamodbv2.util.Tables;
public class StackOverflow {
private static final String EXAMPLE_TABLE_NAME = "example_table";
public static void main(String[] args) {
AmazonDynamoDB client = new AmazonDynamoDBClient(new BasicAWSCredentials("accessKey", "secretKey"));
client.setEndpoint("http://localhost:4000");
DynamoDB dynamoDB = new DynamoDB(client);
if (Tables.doesTableExist(client, "example_table")) client.deleteTable(EXAMPLE_TABLE_NAME);
// Create table with hash key 'customer_id'
CreateTableRequest createTableRequest = new CreateTableRequest();
createTableRequest.withTableName(EXAMPLE_TABLE_NAME);
createTableRequest.withKeySchema(new KeySchemaElement("customer_id", KeyType.HASH));
createTableRequest.withAttributeDefinitions(new AttributeDefinition("customer_id", ScalarAttributeType.S));
createTableRequest.withProvisionedThroughput(new ProvisionedThroughput(15l, 15l));
dynamoDB.createTable(createTableRequest);
Tables.waitForTableToBecomeActive(client, EXAMPLE_TABLE_NAME);
Table exampleTable = dynamoDB.getTable(EXAMPLE_TABLE_NAME);
exampleTable.putItem(new Item()
.withPrimaryKey("customer_id", "ABCD")
.withString("customer_name", "Jim")
.withString("customer_email", "jim#gmail.com"));
System.out.println("After Jim:");
exampleTable.scan()
.forEach(System.out::println);
System.out.println();
try {
exampleTable.putItem(new Item()
.withPrimaryKey("customer_id", "EFGH")
.withString("customer_name", "Garret")
.withString("customer_email", "garret#gmail.com"), new Expected("customer_id").notExist());
} catch (ConditionalCheckFailedException e) {
System.out.println("Conditional check failed!");
}
System.out.println("After Garret:");
exampleTable.scan()
.forEach(System.out::println);
System.out.println();
try {
exampleTable.putItem(new Item()
.withPrimaryKey("customer_id", "ABCD")
.withString("customer_name", "Bob")
.withString("customer_email", "bob#gmail.com"), new Expected("customer_id").notExist());
} catch (ConditionalCheckFailedException e) {
System.out.println("Conditional check failed!");
}
System.out.println("After Bob:");
exampleTable.scan()
.forEach(System.out::println);
}
}
Output:
After Jim:
{ Item: {customer_email=jim#gmail.com, customer_name=Jim, customer_id=ABCD} }
After Garret:
{ Item: {customer_email=garret#gmail.com, customer_name=Garret, customer_id=EFGH} }
{ Item: {customer_email=jim#gmail.com, customer_name=Jim, customer_id=ABCD} }
Conditional check failed!
After Bob:
{ Item: {customer_email=garret#gmail.com, customer_name=Garret, customer_id=EFGH} }
{ Item: {customer_email=jim#gmail.com, customer_name=Jim, customer_id=ABCD} }
Thare is a tutorial at javaFX documentation page. This example describes how to make tableView, if you have some sertain java class, which can tell you which columns you are going to have. (That is a Person class in this example).
But what if i do not have any specific class, and number of columns can vary from time to time?
In my case i have such data structure:
class TableData{
List<Row> rows; //A list with all my rows i need to have in my table
}
class Row{
List<Column> columns; //Cells\Columns for every row.
}
class Column{
Attribute attr; //Each column - is somethig like a wrapper for the real data i need to show in a cell;
}
class Attribute{ //My precues data
String name;
SupportingInfo info;
}
class SupportingInfo{//Some supporting fields...
String name;
String value;
//...etc....
}
So, my case is very similar to this one.
The only differents is that data from the case above is not binded with its representation in javaFX table (so, even if some one will make extra controls to edit this data in a tableView, the actual object with that data will never know about it.), because it(data) goes to the table like some strings, not like some objects;
So, what do i need - is to push data to the table (like that: table.setItems(tableData)), set some set Factories, to give user ability to edit data, and to have this edited data in my tableData object;
Here are some code ive tried to make for this purpose:
//prepare my table
private void createTableHeader(TableView table, List<Attribute> ias) {
int i = 0;
for (final Attribute ia : ias) {
final int j = i;
i++;
TableColumn tc = new TableColumn(ia.getName());
tc.setSortable(true);
tc.setCellValueFactory(new Callback<CellDataFeatures<List<Attribute>, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(CellDataFeatures<List<Attribute>, String> arg0) {
if(arg0.getValue().get(j).getSupportingInfo() == null){
arg0.getValue().get(j).setSupportingInfo(new SupportingInfo());
}
return new SimpleObjectProperty(arg0.getValue().get(j),"value");
}
});
table.getColumns().add(tc);
}
}
//loading some data to my tableView
private void createTableBody(TableView curTable, List<Row> rows) {
ObservableList<List<Attribute>> data = FXCollections.observableArrayList();
for (Row row : rows) {
data.add(row.getColumns());
}
curTable.setItems(data);
}
//this one is to define some extra controls for editing data in a table by users
private void makeCellFactory(TableColumn curTableCol, final Attribute templateIa, final Document doc) {
curTableCol.setCellFactory(new Callback<TableColumn, TableCell>() {
public TableCell call(TableColumn p) {
final EditingCell cell = new EditingCell(templateIa, doc);
return cell;
}
});
}
But, as a result, i have just empty rows in my table, with an ability to click some cell and recieve table editing controls. But there is not defult values in by table;
What am i doing wrong in my code?
Ok, i've found a solution:
ts.setCellFactory should look like this:
tc.setCellValueFactory(new Callback<CellDataFeatures<List<Attribute>, SupportingInfo>, ObservableValue<Attribute>>() {
#Override
public ObservableValue<Attribute> call(CellDataFeatures<List<Attribute>, SupportingInfo> arg0) {
return new SimpleObjectProperty(arg0.getValue().get(j),"value",arg0.getValue().get(j));
}
});
Also, this code is needed to catch new values and put the incoming data to the table:
tc.setOnEditCommit(new EventHandler<CellEditEvent<List<Attribute>, Attribute>>() {
#Override
public void handle(CellEditEvent<List<Attribute>, Attribute> t) { t.getTableView().getItems().get(t.getTablePosition().getRow()).get(j).setSupportingInfo(t.getNewValue().getSupportingInfo());
}
});