vaadin / vaadin/spring

Using Beans in composite

Open
#526 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement needs design
Dominant language
Java
Stars
186
Forks
98
PR merge metrics
No merged PRs in 30d

Description

I have a class like this

@SpringComponent
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class CardView extends Div {

    @Autowired
    public CardView(...some services...) {
        ...
    }
}

which I would like to use in a composite:

public class SpringCompositeDemo extends Composite<CardView> {

This is currently not possible. My workaround is to extend Composite:

@SpringComponent
public abstract class SpringComposite<T extends Component> extends Composite<T> {
    private ApplicationContext applicationContext;

    @SuppressWarnings("unchecked")
    @Override
    protected T initContent() {
        Class<? extends Component> contentType = findContentType((Class<? extends Composite<?>>) getClass());
        if (AnnotationUtils.findAnnotation(contentType, org.springframework.stereotype.Component.class) != null)
            if (applicationContext != null) {
                return (T) applicationContext.getBean(contentType);
            } else {
                throw new IllegalStateException("Cannot access Composite content before bean initialization");
            }
        return (T) ReflectTools.createInstance(contentType);
    }

    @Autowired
    public final void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    /*
     * copied from Composite#findContentType(Class)
     */
    private static Class<? extends Component> findContentType(
            Class<? extends Composite<?>> compositeClass) {
        Type type = GenericTypeReflector.getTypeParameter(
                compositeClass.getGenericSuperclass(),
                Composite.class.getTypeParameters()[0]);
        if (type instanceof Class || type instanceof ParameterizedType) {
            return GenericTypeReflector.erase(type).asSubclass(Component.class);
        }
        throw new IllegalStateException(getExceptionMessage(type));
    }

    /*
     * copied from Composite#getExceptionMessage(Type)
     */
    private static String getExceptionMessage(Type type) {
        if (type == null) {
            return "Composite is used as raw type: either add type information or override initContent().";
        }

        if (type instanceof TypeVariable) {
            return String.format(
                    "Could not determine the composite content type for TypeVariable '%s'. "
                            + "Either specify exact type or override initContent().",
                    type.getTypeName());
        }
        return String.format(
                "Could not determine the composite content type for %s. Override initContent().",
                type.getTypeName());
    }
}

It would be nice to have this work out of the box.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Composite.initContent(), findContentType(), and the Spring ApplicationContext bean-creation path described in the issue. Reproduce the CardView and SpringCompositeDemo examples, then determine the integration needed for Spring-managed composite content. Done means a prototype-scoped Spring component can be used as Composite content without the custom SpringComposite workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.