CKEditor null pointer exception if field value is null

As posted by ba-num-vu on 9/28/2011 in an unrelated topic:

I’ve never seen this bug. Do you have a code sample? Why not just fix your beanitem so it’s not null. It simply is not valid to say your HTML value is null. I don’t mind fixing it if we understand the issue better (like an example that shows it).

By the time paintContent is called, it seems a value should be set. The constructor for CKEditorTextField does a super.setValue(“”), so it should not have a null value anyway.

And it’s setValue(Object newValue) tests if newValue is null, it sets it to the empty string, too.

And it’s changeVariables() also tests if the newValue is null, setting it to the empty string.

I am not sure how your widget’s value even became null. Are you using the latest version in the Directory?

Is it possible you are passing in a value that is neither null nor a String?

Since I’m not sure what exactly the bug report was (no example, so cannot test to prove it has been fixed), we made a patch attempting to fix any possible areas. But mostly, passing ‘null’ would not cause it, but perhaps if you passed in an object that isn’t a String since there were assumptions it was in castings. Now we just use object.toString() so if you pass an object that doesn’t create HTML, you’ll at least see the object as string value.

Anyway, the Directory has a new 1.4.2 version that also includes CKEditor 3.6.2. Please give it a test and hopefully it’ll fix the problem you saw. But again, you should really not be passing in null for the HTML value and expect it to work as that’s a programming bug, not an API issue.

Sorry for the late reply and seems that I dig the old post again, but here is the code:
User.java


public class User{
    
        private String username;
        private String password;
        
        public User(){}
        public User(String userName, String pass){
            this.username = userName;
            this.password = pass;
        }
        
        public String getUsername(){
            return this.username;
        }
        
        public void setUsername(String name){
            this.username = name;
        }
        
        public String getPassword(){
            return this.password;
        }
        
        public void setPassword(String pass){
            this.password = pass;
        }
    }

init method of MainApp and nested class CustomDataBinding


    @Override
    public void init() {
        final Window mainWindow = new Window();
        mainWindow.setSizeFull();
        setMainWindow(mainWindow);
        mainWindow.getContent().setSizeFull();
        config = new CKEditorConfig();
        config.useCompactTags();
        config.disableElementsPath();
        config.setResizeDir(CKEditorConfig.RESIZE_DIR.HORIZONTAL);
        config.disableSpellChecker();
        config.setToolbarCanCollapse(false);
        config.enableTableResizePlugin();
        config.setHeight("300px");

        Form f = new Form();
        mainWindow.addComponent(f);
        f.setFormFieldFactory(new CustomDataBinding());
        /*
                 Here if I user User u = new User(); then set username = "testesttest"; the error will not shown
        */
        BeanItem<User> item = new BeanItem<User>(new User());
        f.setItemDataSource(item);
    }
    
        
    private class CustomDataBinding<T> implements FormFieldFactory{

        @Override
        public Field createField(Item item, Object propertyId, Component uiContext) {
            Field f = null;
            if(propertyId.equals("username")){
                CKEditorTextField c = new CKEditorTextField(config);
                c.setHeight("400px");
                f = c;
            }else{
                f = new TextField();
            }
            return f;
        }
    
    }

And for the problem passing null value, in my opinion it’s also a good thing to check if null value is passed. As for in your code, you use the


target.addVariable(this, VCKEditorTextField.VAR_TEXT, getValue().toString());

the getValue can return null, so using it without checking is also a bad behaviour.
If every time user has to set the value before passing in multiple code file, while don’t we check the value on the server or in our component again before generate view? This will reduce the amount of code. And one more question, why don’t you add the setNullValueDisplay as other component of Vaadin?

We created the new 1.4.2 version just to try to handle your case, though without any real info on how you even got the value to be null in the first place.

But we did change paintContent() to use:

Object currValueObject = getValue();
target.addVariable(this, VCKEditorTextField.VAR_TEXT, currValueObject == null ? "" : currValueObject.toString());

And we changed changeVariables() to use:

Object newVarTextObject = variables.get(VCKEditorTextField.VAR_TEXT);
String newValue = newVarTextObject == null ? "" : newVarTextObject.toString();
Object currValueObject = getValue();
final String oldValue = currValueObject == null ? "" : currValueObject.toString();

We’re doing this only because of your problem since if the value is always a String, and setValue() does not allow the value to be null, and the constructor for the widget sets it to an empty string, how the value can ever be null or a non-String mystifies me unless you pass in a value that wasn’t even a String object.

But your example is most unusual in that we certainly never figured anybody would be using a HTML editor to set a user’s name.

And even if the User.username was passed in, that should have resulted in a call to CKEditorTextField.setValue(null) which should have converted that to an empty string.

    	if ( newValue == null )
    		newValue = "";
    	super.setValue(newValue, false);

We just created a 1.4.3 release to include a small tweak just in case the Object passed in is not a String (the only way we can think it could somehow end up with a null value), though we see no real reason why an HTML editor should need to deal with anything else.

    	if ( newValue == null )
    		newValue = "";
    	super.setValue(newValue.toString(), false);

Our code is free to use, so make changes as you see fit. We built the component for our own needs, but did it in a way we hope others can use as well and donated it to the Directory, but if it doesn’t meet your needs, you’ll probably need to expand on it (or replace it) as it does everything we need it to do to work within the Vaadin framework.

Thanks, but the class user is only for example purpose. The User class may have some little self about field, and I want the user to customise it like they would using CK.
And when creating database, there are fields that we allow their value to be null, and it’s not ‘very’ good to every time you encounter that field, you have to set its value to “”.
But really thank you for the great component, and for your care about my problem.
Greeting from Vietnam
Dan Le