wicketstuff / core

Wicketstuff-core projects are bundled user contributions for use with Apache Wicket (https://wicket.apache.org/). They are released in step with Wicket releases to make them easy to use.
342 stars 298 forks source link

LazyModel should support LoadableDetachableModels #569

Closed jan-krakora closed 7 years ago

jan-krakora commented 7 years ago

We are using wicket-modelfactory in our application but we would like to switch to the LazyModel because it doesn't require to run on a Wicket's request thread.

Unfortunately there is a problem with LoadableDetachableModels, because LazyModel is not able to detect the target type from them.

It would be nice to add support for this kind of models. I suppose wicket-modelfactory gets the target type using Google's gentyref library. All code is in the org.wicketeer.modelfactory.ModelFactory class:

public static <T> T from(final IModel<T> model) throws NullPointerException {
    ...
    Class<? extends IModel> c = model.getClass();
    Class<T> type = null;

    Type typeParameter = GenericTypeReflector.getTypeParameter(c, IModel.class.getTypeParameters()[0]);
    if (typeParameter instanceof Class) {
        type = (Class<T>) typeParameter;
    }
    ...
}
svenmeier commented 7 years ago

wicket-lazymodel already supports reading from generic type parameters.

Note that wicket-modelfactory calls #getObject() as last resort:

https://github.com/uweschaefer/wicket-modelfactory/blob/master/src/main/java/org/wicketeer/modelfactory/ModelFactory.java#L134

I assume this is the case here too. If you think otherwise please give us a testcase that fails with lazymodel. Thanks.

jan-krakora commented 7 years ago
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.wicketstuff</groupId>
            <artifactId>wicketstuff-lazymodel</artifactId>
            <version>7.6.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>

                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
import static org.wicketstuff.lazymodel.LazyModel.from;
import static org.wicketstuff.lazymodel.LazyModel.model;

import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.wicketstuff.lazymodel.LazyModel;

public class TestCase {

    //*******************************************
    // Methods
    //*******************************************

    public static void main(String[] args) {
        new TestCase().test(new BeanModel());
    }

    private void test(IModel<Bean> inputModel) {
        IModel<Integer> valueModel = model(from(inputModel).getValue());
        System.out.println(valueModel.getObject());
    }

    //*******************************************
    // Inner classes
    //*******************************************

    private static class Bean {

        //*******************************************
        // Atributes
        //*******************************************

        private int value;

        //*******************************************
        // Getters / setters
        //*******************************************

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

    }

    private static class BeanModel extends LoadableDetachableModel<Bean> {

        @Override
        protected Bean load() {
            return new Bean();
        }

    }

}

Tested on java 1.8.0_91. Result is

Exception in thread "main" org.apache.wicket.WicketRuntimeException: cannot detect target type
    at org.wicketstuff.lazymodel.LazyModel.from(LazyModel.java:585)
    at TestCase.test(TestCase.java:20)
    at TestCase.main(TestCase.java:16)

The same test with wicket-modelfactory works. I have tried debugging it and the target type is really obtained using the Google's gentyref library.

svenmeier commented 7 years ago

You're right! The relevant code is in wicketstuff-lazymodel already, it just wasn't used to resolve a possible type variable on #getObject().

Thanks!