finding the selected row - datamodel

I found the following example in core JSF book, this example use data model to finding the selected row then delete it.
But i found an error in this line names.remove(nameToDelete);
can you help me how can i solve this?
package com.jsf.model;
import java.io.Serializable;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;
public class TableData implements Serializable {
private static final Names[] names = new Names[] {
new Names("William", "Dupont"),
new Names("Anna", "Keeney"),
new Names("Mariko", "Randor"),
new Names("John", "Wilson")
};
private DataModel<Names> model = new ArrayDataModel<Names>(names);
public DataModel<Names> getNames() { return model; }
public String deleteRow() {
Names nameToDelete = model.getRowData();
names.remove(nameToDelete);
return null;
}
}
thanks all

You are calling remove() on names, an array of Names. Arrays do not have the remove function specified - you want to call it on model.

Related

Two-way binding in Android with data from Room database

I am new to the MVVM architecture in Android, and I have some days with a doubt that I consider basic, but that I can't solve.
I proceed to discuss my problem:
I have an Entity, CustomerView (this entity is created from a DatabaseView):
#DatabaseView("select ... ")
public class CustomerView {
public String cardCode;
public String cardName;
public String cardFName;
...
Then, I have a Dao class:
#Dao
public interface OCRD_DAO {
...
#Query("SELECT * from CustomerView where cardCode= :cardCode")
LiveData<CustomerView> getCustomerViewByCardCode(String cardCode);
...
}
The repository class, makes use of the DAO class:
public LiveData<CustomerView> getCustomer(String cardCode){
return mOcrdDao.getCustomerViewByCardCode(cardCode);
}
The CustomerSheetViewModel class:
public class CustomerSheetViewModel extends BaseObservable {
private Repository mRepository;
public LiveData<CustomerView> mCustomer;
private MutableLiveData<String> _cardName;
#Bindable
public MutableLiveData<String> getCardName(){
return this._cardName;
}
public MutableLiveData<String> setCardName(String value){
// Avoids infinite loops.
if (mCustomer.getValue().cardName != value) {
mCustomer.getValue().cardName = value;
// React to the change.
saveData();
// Notify observers of a new value.
notifyPropertyChanged(BR._cardName);
}
}
public CustomerSheetViewModel (Application application, String cardCode) {
mRepository = new Repository(application);
this.mCustomer = mRepository.getCustomer(cardCode);
//Init MutableLiveData????
this._cardName = this.mCustomer.getValue().cardName;
//Null Exception, because this.mCustomer.getValue() is null
}
}
At this point, my problem occurs: when I initialise the CustomerView object, it is of type LiveData. However, if I want to make use of 2-way binding, I need an object of type MutableLiveData. So, I think I should create the MutableLiveData object with the data extracted from the database (i.e. from the call to the repository). When I try this (e.g. getValue().cardName) a null exception is thrown, since LiveData is asynchronous.
Finally, I could make use of this property in the layout:
android:text="#={customerSheetViewModel.cardName}"
I really appreciate any help, as I can't find any reference to 2-way binding when the data comes from a database read.
Thanks in advance.

BIRT: scripted datasource cannot access public methods

I´m trying to set up a scripted Datasource using pojos from my app (java 1.8).
I embedded a reportengine (4.4.0) in my app via maven and created a report with a scripted datasourse. The pojos can be seen by the report.
bookSrv = Packages.de.me.service.ReportDataService;
works.
I can access static methods of my object, but whatever i try, accessing public methods or fields results in an exception.
So
books = bookSrv.books;
gives
org.mozilla.javascript.EvaluatorException: Java class "de.me.service.ReportDataService" has no public instance field or method named "books". (/report/data-sets/script-data-set[#id="5"]/method[#name="open"]#11)
or
books = bookSrv.showMyBooks('Peter');
gives
org.mozilla.javascript.EvaluatorException: Java class "de.my.service.ReportDataService" has no public instance field or method named "showMyBooks". (/report/data-sets/script-data-set[#id="5"]/method[#name="open"]#11)
But:
books = Packages.me.tdesk.service.ReportDataService.myBooksStatic('Peter');
works like expected. (Simply a static wrapper around my method)
here is my java class:
package de.me.service;
import de.me.model.dto.BookDto;
import java.util.ArrayList;
import java.util.List;
public class ReportDataService {
public ReportDataService() {
books = showMyBooks("Peter");
System.out.println("ReportDataService.init()");
}
private List<BookDto> books;
public List<BookDto> getBooks() {
return books;
}
public void setBooks(List<BookDto> books) {
this.books = books;
}
public List<BookDto> showMyBooks(String commodity){
BookDto dto = new BookDto(12l, "otto", "My", 12l);
List<BookDto> books = new ArrayList<>();
books.add(dto);
dto = new BookDto(122l, "paul", "My", 122l);
books.add(dto);
return books;
}
public static List<BookDto> myBooksStatic(String commodity){
ReportDataService rep = new ReportDataService();
return rep.showMyBooks(commodity);
}
}
Many thanks
Uli
Hmm...
shouldn't it be
bookSrv = new Packages.de.me.service.ReportDataService(...);
instead of
bookSrv = Packages.de.me.service.ReportDataService;
?
With the second one, bookSrv will be the Java class ReportDataService (which is an object in Rhinoscript), not an instance of the class.

Deserialise JSON fields based on user role

I have some fields in a model that I only want to be returned when the logged in user has the role ROLE_ADMIN. I can use #JsonIgnore but that hides it for everyone. How can I make it hide dynamically?
You should use Jackson Json Views technology to acheive it - it allows to choose a different set of fields to be serialized programatically. It is also supported by Spring
Consider you have a class Model with two properties: commonField which should be available for everyone and secretField which should be available only for certain users. You should create an hierarchy of views (any classes would work) and specify which field is available in which view using #JsonView annotation
package com.stackoverflow.jsonview;
import com.fasterxml.jackson.annotation.JsonView;
public class Model {
public static class Public {}
public static class Secret extends Public {}
#JsonView(Public.class)
private String commonField;
#JsonView(Secret.class)
private String secretField;
public Model() {
}
public Model(String commonField, String secretField) {
this.commonField = commonField;
this.secretField = secretField;
}
public String getCommonField() {
return commonField;
}
public void setCommonField(String commonField) {
this.commonField = commonField;
}
public String getSecretField() {
return secretField;
}
public void setSecretField(String secretField) {
this.secretField = secretField;
}
}
Now you can specify the view you want to use in concrete ObjectMapper
package com.stackoverflow.jsonview;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*/
public class ModelTest {
#Test
public void testSecretField() throws JsonProcessingException {
Model model = new Model("commonField","secretField");
assertEquals("{\"commonField\":\"commonField\",\"secretField\":\"secretField\"}", new ObjectMapper().writerWithView(Model.Secret.class).writeValueAsString(model));
assertEquals("{\"commonField\":\"commonField\"}", new ObjectMapper().writerWithView(Model.Public.class).writeValueAsString(model));
}
}
I am not sure if you can use declaratie approach to make spring choose the right view based on user role out of the box, so probably you will have to write some code like this:
#RequestMapping("/data")
public String getData(HttpServletRequest request) {
Model model = service.getModel();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper = request.isUserInRole("ROLE_ADMIN") ? objectMapper.writerWithView(Model.Secret.class) : objectMapper.writerWithView(Model.Public.class);
return objectMapper.writeValueAsString(model);
}
I solved this after literally a full month of trying various things. I'm working with Spring 4.3.1 and boot, with data being returned in Hal using a pagedrepository.
extend RepositoryRestMvcConfiguration as MyRepositoryRestMvcConfiguration and add #Configuration to the class, make sure your starter class has #EnableWebMvc
add this to MyRepositoryRestMvcConfiguration- extend TypeConstrainedMappingJackson2HttpMessageConverter as MyResourceSupportHttpMessageConverter
add this to MyRepositoryRestMvcConfiguration
#Override
#Bean
public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter() {
ArrayList<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(MediaTypes.HAL_JSON);
if (config().useHalAsDefaultJsonMediaType()) {
mediaTypes.add(MediaType.APPLICATION_JSON);
}
int order = config().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10
: Ordered.LOWEST_PRECEDENCE - 1;
TypeConstrainedMappingJackson2HttpMessageConverter converter = new MyResourceSupportHttpMessageConverter(
order);
converter.setObjectMapper(halObjectMapper());
converter.setSupportedMediaTypes(mediaTypes);
converter.getObjectMapper().addMixIn(Object.class, MyFilteringMixin.class);
final FilterProvider myRestrictionFilterProvider = new SimpleFilterProvider()
.addFilter("MyFilteringMixin", new MyPropertyFilter()).setFailOnUnknownId(false);
converter.getObjectMapper().setFilterProvider(myRestrictionFilterProvider);
return converter;
}
Create an empty Mixin
package filters;
import com.fasterxml.jackson.annotation.JsonFilter;
#JsonFilter("MyFilteringMixin")
public class MyFilteringMixin {}
Create an empty Mixin
create class MyPropertyFilter extending SimpleBeanPropertyFilter and override adapt this method
serializeAsField(Object, JsonGenerator, SerializerProvider, PropertyWriter)you need to call either super.serializeAsField(pPojo, pJgen, pProvider, pWriter) or pWriter.serializeAsOmittedField(pPojo, pJgen, pProvider) depending on whether you wish to include or discard this particular field.
I added an annotation to the particular fields I wanted to alter and interrogated that annotation when deciding which of these two to call. I injected the security role and stored permitted roles in the annotation.
This alters what Hal shares out to the caller, not what Hal is holding in its repository. Thus you can morph it depending on who the caller is.

SPEL (Spring Expression Language) Collection Selection calling methods/functions in selection

I am trying to write simple validation rules with SpEL
I want to be able to say something like, "Do any elements in the List have a value greater then x". Simple case works fine, but I wanted to extend it to get the absolute value first and then do the greater than test
If I try to call methods or functions as part of the criteria to select from a collection. it seems to loose the context that I am working with an item in the collection
import java.util.Arrays;
import java.util.List;
public class BeanClass {
private final List<ListOf> list;
public BeanClass(ListOf... list){
this.list = Arrays.asList(list);
}
public List<ListOf> getList(){
return list;
}
}
public class ListOf {
private final double value;
public ListOf(double v) {
this.value = v;
}
public double getValue() {
return value;
}
}
import org.junit.Test;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import static org.junit.Assert.assertTrue;
public class SpelTest {
#Test
public void test(){
ExpressionParser parser = new SpelExpressionParser();
// works as expected
Expression expression1 = parser.parseExpression("list.?[ value>2 ].size()!=0");
assertTrue(expression1.getValue(new BeanClass(new ListOf(1.1), new ListOf(2.2)), Boolean.class));
Expression expression2 = parser.parseExpression("list.?[ T(java.lang.Math).abs(value) > 2 ].size()!=0");
// get this error:
//org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 5): Property or field 'value' cannot be found on object of type 'BeanClass' - maybe not public?
assertTrue(expression2.getValue(new BeanClass(new ListOf(1.1), new ListOf(-2.2)), Boolean.class));
}
}
I have played with defining my own function and registering it
Experimented with #this as well
Looks like an issue, though: https://jira.spring.io/browse/SPR-12035
As a cunclusion: you can't use method invocation within selectionExpression for items.
You need to add #this to refer the current item, for example:
Expression expression2 = parser.parseExpression("list.?[ T(java.lang.Math).abs(#this.getValue()) > 2 ].size()!=0");

Gson.toJson() and inheriting from a generic class

I have the following class:
public static class TestSomething {
Integer test;
public TestSomething(Integer test) {
this.test = test;
}
// getter and setter for test
}
Ok, now create a collection of this class and serialize it with Gson:
Collection<TestSomething> tests = Arrays.asList(
new TestSomething(1),
new TestSomething(2),
new TestSomething(3)
);
String json = new Gson().toJson(tests, new TypeToken<Collection<TestSomething>>() {}.getType());
After this, the String json is set to
[{"test":1},{"test":2},{"test":3}]
Which is great.
But now, all of my model classes inherit from a generic type Identifiable<T> which provides just two methods T getId() and void setId(T). So I change the TestSomething-class from above to
public static class TestSomething extends Identifiable<Long> {
// same as above
}
When I try to put this through Gson.toJson(), Gson ends up with the following Exception:
java.lang.UnsupportedOperationException: Expecting parameterized type, got class path.to.TestSomething.
Are you missing the use of TypeToken idiom?
See http://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener
at com.google.gson.TypeInfoFactory.getActualType(TypeInfoFactory.java:97)
...
So, what do I have to do to get this work?
I don't know the answer, but I know that generic type resolution is a tricky thing to get right: specifically full type resolution from interface with type parameter T up through to generic parameter declaration (T=Long). In these cases it is not enough to check for Method object's parameters but also resolve generic type parameters. This is most likely what causes issues; it may be a bug in Gson.
Since you are serializing things, perhaps you could just omit any type declarations? Although your TypeToken is correct for the use case, maybe it confuses Gson.
But just in case you could not make Gson work with this, I know that of other JSON libraries Jackson can handle such cases correctly.
Perhaps this issue was resolved in one of the Gson releases newer than what the original questioner was using, because the example in the original question now serializes as expected.
// output:
// [{"test":1},{"test":2},{"test":3}]
import java.util.Arrays;
import java.util.Collection;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class Foo
{
public static void main(String[] args)
{
Collection<TestSomething> tests = Arrays.asList(
new TestSomething(1),
new TestSomething(2),
new TestSomething(3));
String json = new Gson().toJson(tests, new TypeToken<Collection<TestSomething>>() {}.getType());
System.out.println(json);
}
}
class TestSomething extends Identifiable<Long>
{
Integer test;
public TestSomething(Integer test)
{
this.test = test;
}
#Override
Long getId()
{
return new Long(test);
}
#Override
void setId(Long t)
{
this.test = (int)(t.longValue());
}
}
abstract class Identifiable<T>
{
abstract T getId();
abstract void setId(T t);
}

Resources