This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.10.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.10.x by this push:
new eb472155f4c CAMEL-21794: camel-jbang - Export bean with lazy-bean
should not initialize the bean if not needed (#17264)
eb472155f4c is described below
commit eb472155f4c6a4b835d0352a22b095739cbde6a4
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Feb 25 14:54:59 2025 +0000
CAMEL-21794: camel-jbang - Export bean with lazy-bean should not initialize
the bean if not needed (#17264)
* CAMEL-21794: camel-jbang - Export bean with lazy-bean should not
initialize the bean if not needed
---
.../camel/component/consul/ConsulRegistry.java | 6 ++
.../main/java/org/apache/camel/spi/Registry.java | 28 ++++++-
...efaultDependencyInjectionAnnotationFactory.java | 12 ++-
...oRegistrySupplierBeanInitDestroyMethodTest.java | 91 ++++++++++++++++++++++
.../org/apache/camel/support/DefaultRegistry.java | 38 +++++++--
.../org/apache/camel/support/SimpleRegistry.java | 6 ++
.../dsl/jbang/core/commands/ExportBaseCommand.java | 4 +-
.../camel/dsl/jbang/core/commands/ExportTest.java | 2 +-
.../camel/dsl/xml/io/XmlRoutesBuilderLoader.java | 44 ++++++++++-
.../dsl/yaml/deserializers/BeansDeserializer.java | 44 ++++++++++-
10 files changed, 258 insertions(+), 17 deletions(-)
diff --git
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulRegistry.java
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulRegistry.java
index 27c8231fd14..ee3e36b090e 100644
---
a/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulRegistry.java
+++
b/components/camel-consul/src/main/java/org/apache/camel/component/consul/ConsulRegistry.java
@@ -171,6 +171,12 @@ public class ConsulRegistry implements Registry {
throw new UnsupportedOperationException("Binding with supplier not
supported");
}
+ @Override
+ public void bind(String id, Class<?> type, Supplier<Object> bean, String
initMethod, String destroyMethod)
+ throws RuntimeCamelException {
+ throw new UnsupportedOperationException("Binding with supplier not
supported");
+ }
+
@Override
public void bindAsPrototype(String id, Class<?> type, Supplier<Object>
bean) throws RuntimeCamelException {
throw new UnsupportedOperationException("Binding with supplier not
supported");
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/Registry.java
b/core/camel-api/src/main/java/org/apache/camel/spi/Registry.java
index be0d24b4e7e..48601f45ade 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/Registry.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/Registry.java
@@ -29,7 +29,7 @@ public interface Registry extends BeanRepository {
/**
* Binds the bean to the repository (if possible).
*
- * If the bean is {@link CamelContextAware} then the registry will
automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will
automatically inject the context if possible.
*
* @param id the id of the bean
* @param bean the bean
@@ -44,7 +44,7 @@ public interface Registry extends BeanRepository {
/**
* Binds the bean to the repository (if possible).
*
- * If the bean is {@link CamelContextAware} then the registry will
automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will
automatically inject the context if possible.
*
* @param id the id of the bean
* @param bean the bean
@@ -63,7 +63,7 @@ public interface Registry extends BeanRepository {
* <p/>
* Binding by id and type allows to bind multiple entries with the same id
but with different type.
*
- * If the bean is {@link CamelContextAware} then the registry will
automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will
automatically inject the context if possible.
*
* @param id the id of the bean
* @param type the type of the bean to associate the
binding
@@ -77,7 +77,7 @@ public interface Registry extends BeanRepository {
* <p/>
* Binding by id and type allows to bind multiple entries with the same id
but with different type.
*
- * If the bean is {@link CamelContextAware} then the registry will
automatic inject the context if possible.
+ * If the bean is {@link CamelContextAware} then the registry will
automatically inject the context if possible.
*
* @param id the id of the bean
* @param type the type of the bean to associate the
binding
@@ -103,6 +103,26 @@ public interface Registry extends BeanRepository {
*/
void bind(String id, Class<?> type, Supplier<Object> bean) throws
RuntimeCamelException;
+ /**
+ * Binds the bean to the repository (if possible).
+ * <p/>
+ * Camel will cache the result from the supplier from first lookup
(singleton scope). If you do not need cached then
+ * use {@link #bindAsPrototype(String, Class, Supplier)} instead.
+ * <p/>
+ * Binding by id and type allows to bind multiple entries with the same id
but with different type.
+ *
+ * If the bean is {@link CamelContextAware} then the registry will
automatically inject the context if possible.
+ *
+ * @param id the id of the bean
+ * @param type the type of the bean to associate the
binding
+ * @param bean a supplier for the bean
+ * @param initMethod optional init method (invoked at bind)
+ * @param destroyMethod optional destroy method (invoked at
unbind or stopping Camel)
+ * @throws RuntimeCamelException is thrown if binding is not possible
+ */
+ void bind(String id, Class<?> type, Supplier<Object> bean, String
initMethod, String destroyMethod)
+ throws RuntimeCamelException;
+
/**
* Binds the bean (via a supplier) to the repository (if possible).
* <p/>
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
index b665e0209fe..c7010906870 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultDependencyInjectionAnnotationFactory.java
@@ -52,6 +52,12 @@ public class DefaultDependencyInjectionAnnotationFactory
public Runnable createBindToRegistryFactory(
String id, Object bean, Class<?> beanType, String beanName,
boolean beanPostProcess,
String initMethod, String destroyMethod) {
+
+ if (beanType.isAssignableFrom(Supplier.class)) {
+ beanType = Object.class;
+ }
+ final Class<?> beanTarget = beanType;
+
return () -> {
if (beanPostProcess) {
try {
@@ -66,7 +72,11 @@ public class DefaultDependencyInjectionAnnotationFactory
if (bean instanceof Supplier) {
// must be Supplier<Object> to ensure correct binding
Supplier<Object> sup = (Supplier<Object>) bean;
- camelContext.getRegistry().bind(id, beanType, sup);
+ if (initMethod != null || destroyMethod != null) {
+ camelContext.getRegistry().bind(id, beanTarget, sup,
initMethod, destroyMethod);
+ } else {
+ camelContext.getRegistry().bind(id, beanTarget, sup);
+ }
} else {
if (initMethod != null || destroyMethod != null) {
camelContext.getRegistry().bind(id, bean, initMethod,
destroyMethod);
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/BindToRegistrySupplierBeanInitDestroyMethodTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/BindToRegistrySupplierBeanInitDestroyMethodTest.java
new file mode 100644
index 00000000000..218a19b3e12
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/impl/BindToRegistrySupplierBeanInitDestroyMethodTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl;
+
+import java.util.function.Supplier;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.spi.CamelBeanPostProcessor;
+import org.apache.camel.support.PluginHelper;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class BindToRegistrySupplierBeanInitDestroyMethodTest extends
ContextTestSupport {
+
+ @BindToRegistry(initMethod = "start", destroyMethod = "stop")
+ public Supplier<FooService> myFoo() {
+ return () -> new FooService("World");
+ }
+
+ @Test
+ public void testStop() throws Exception {
+ // bean post processing dont run on ContextTestSupport
+ CamelBeanPostProcessor cbpp =
PluginHelper.getBeanPostProcessor(context);
+ cbpp.postProcessBeforeInitialization(this, "this");
+ cbpp.postProcessAfterInitialization(this, "this");
+
+ FooService foo = context.getRegistry().lookupByNameAndType("myFoo",
FooService.class);
+ assertNotNull(foo);
+ assertEquals("Started World", foo.getMessage());
+
+ // stop camel should trigger destroy
+ context.stop();
+
+ assertEquals("Stopped", foo.getMessage());
+ }
+
+ @Test
+ public void testUnbind() throws Exception {
+ // bean post processing dont run on ContextTestSupport
+ CamelBeanPostProcessor cbpp =
PluginHelper.getBeanPostProcessor(context);
+ cbpp.postProcessBeforeInitialization(this, "this");
+ cbpp.postProcessAfterInitialization(this, "this");
+
+ FooService foo = context.getRegistry().lookupByNameAndType("myFoo",
FooService.class);
+ assertNotNull(foo);
+ assertEquals("Started World", foo.getMessage());
+
+ // unbind should trigger destroy
+ context.getRegistry().unbind("myFoo");
+ assertEquals("Stopped", foo.getMessage());
+ }
+
+ public static class FooService {
+
+ private String message;
+
+ public FooService(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void start() {
+ this.message = "Started " + message;
+ }
+
+ public void stop() {
+ this.message = "Stopped";
+ }
+
+ }
+}
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
index 182c53e6808..2e4c753ddef 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultRegistry.java
@@ -214,6 +214,29 @@ public class DefaultRegistry extends ServiceSupport
implements Registry, LocalBe
}
}
+ @Override
+ public void bind(String id, Class<?> type, Supplier<Object> bean, String
initMethod, String destroyMethod)
+ throws RuntimeCamelException {
+ if (bean != null) {
+ // wrap in cached supplier (memorize)
+ Supplier<Object> sup = Suppliers.memorize(() -> {
+ Object answer = bean.get();
+ if (isNotEmpty(initMethod)) {
+ try {
+ ObjectHelper.invokeMethodSafe(initMethod, answer);
+ } catch (Exception e) {
+ throw
RuntimeCamelException.wrapRuntimeCamelException(e);
+ }
+ }
+ return answer;
+ });
+ supplierRegistry.bind(id, type, sup);
+ if (isNotEmpty(destroyMethod)) {
+ beansToDestroy.put(id, new KeyValueHolder<>(sup,
destroyMethod));
+ }
+ }
+ }
+
@Override
public void bindAsPrototype(String id, Class<?> type, Supplier<Object>
bean) throws RuntimeCamelException {
if (bean != null) {
@@ -234,11 +257,16 @@ public class DefaultRegistry extends ServiceSupport
implements Registry, LocalBe
if (holder != null) {
String destroyMethod = holder.getValue();
Object target = holder.getKey();
- try {
-
org.apache.camel.support.ObjectHelper.invokeMethodSafe(destroyMethod, target);
- } catch (Exception e) {
- LOG.warn("Error invoking destroy method: {} on bean: {} due
to: {}. This exception is ignored.",
- destroyMethod, target, e.getMessage(), e);
+ if (target instanceof Supplier sup) {
+ target = sup.get();
+ }
+ if (target != null) {
+ try {
+
org.apache.camel.support.ObjectHelper.invokeMethodSafe(destroyMethod, target);
+ } catch (Exception e) {
+ LOG.warn("Error invoking destroy method: {} on bean: {}
due to: {}. This exception is ignored.",
+ destroyMethod, target, e.getMessage(), e);
+ }
}
}
}
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/SimpleRegistry.java
b/core/camel-support/src/main/java/org/apache/camel/support/SimpleRegistry.java
index 0018f9937a5..388f4222d91 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/SimpleRegistry.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/SimpleRegistry.java
@@ -118,6 +118,12 @@ public class SimpleRegistry extends LinkedHashMap<String,
Map<Class<?>, Object>>
throw new UnsupportedOperationException("Use SupplierRegistry");
}
+ @Override
+ public void bind(String id, Class<?> type, Supplier<Object> bean, String
initMethod, String destroyMethod)
+ throws RuntimeCamelException {
+ throw new UnsupportedOperationException("Use SupplierRegistry");
+ }
+
@Override
public void bindAsPrototype(String id, Class<?> type, Supplier<Object>
bean) {
throw new UnsupportedOperationException("Use SupplierRegistry");
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index 2f019aae06e..aca19671dd0 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -237,9 +237,9 @@ public abstract class ExportBaseCommand extends
CamelCommand {
description = "Whether to ignore route loading and
compilation errors (use this with care!)")
protected boolean ignoreLoadingError;
- @CommandLine.Option(names = { "--lazy-bean" },
+ @CommandLine.Option(names = { "--lazy-bean" }, defaultValue = "true",
description = "Whether to use lazy bean initialization
(can help with complex classloading issues")
- protected boolean lazyBean;
+ protected boolean lazyBean = true;
protected boolean symbolicLink; // copy source files using symbolic
link
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
index 26a9807e750..6565b115b9d 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
@@ -166,7 +166,7 @@ class ExportTest {
@MethodSource("runtimeProvider")
public void shouldExportLazyBean(RuntimeType rt) throws Exception {
Export command = createCommand(rt, new String[] {
"classpath:route.yaml", "file:src/test/resources/LazyFoo.java" },
- "--gav=examples:route:1.0.0", "--dir=" + workingDir,
"--quiet", "--lazy-bean");
+ "--gav=examples:route:1.0.0", "--dir=" + workingDir,
"--quiet", "--lazy-bean=true");
int exit = command.doCall();
Assertions.assertEquals(0, exit);
diff --git
a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
index 534575475fe..9f1448e725d 100644
---
a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
+++
b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
@@ -24,6 +24,8 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
import org.w3c.dom.Document;
@@ -48,9 +50,11 @@ import
org.apache.camel.model.dataformat.DataFormatsDefinition;
import org.apache.camel.model.rest.RestConfigurationDefinition;
import org.apache.camel.model.rest.RestDefinition;
import org.apache.camel.model.rest.RestsDefinition;
+import org.apache.camel.spi.CamelBeanPostProcessor;
import org.apache.camel.spi.Resource;
import org.apache.camel.spi.annotations.RoutesLoader;
import org.apache.camel.support.CachedResource;
+import org.apache.camel.support.PluginHelper;
import org.apache.camel.support.scan.PackageScanHelper;
import org.apache.camel.xml.io.util.XmlStreamDetector;
import org.apache.camel.xml.io.util.XmlStreamInfo;
@@ -391,11 +395,25 @@ public class XmlRoutesBuilderLoader extends
RouteBuilderLoaderSupport {
* {@link #doLoadRouteBuilder}), a failure may lead to delayed
registration.
*/
private void registerBeanDefinition(BeanFactoryDefinition<?> def, boolean
delayIfFailed) {
+ CamelBeanPostProcessor cbpp =
PluginHelper.getBeanPostProcessor(getCamelContext());
+ Predicate<?> lazy = cbpp.getLazyBeanStrategy();
+
String name = def.getName();
String type = def.getType();
try {
- Object target = BeanModelHelper.newInstance(def,
getCamelContext());
- bindBean(def, name, target);
+ // only do lazy bean on 2nd pass as 1st pass may work
+ if (!delayIfFailed && lazy != null && lazy.test(null)) {
+ bindLazyBean(def, name, () -> {
+ try {
+ return BeanModelHelper.newInstance(def,
getCamelContext());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ } else {
+ Object target = BeanModelHelper.newInstance(def,
getCamelContext());
+ bindBean(def, name, target);
+ }
} catch (Exception e) {
if (delayIfFailed) {
delayedRegistrations.add(def);
@@ -417,4 +435,26 @@ public class XmlRoutesBuilderLoader extends
RouteBuilderLoaderSupport {
model.addCustomBean(def);
}
+ protected void bindLazyBean(
+ BeanFactoryDefinition<?> def,
+ String name, Supplier<Object> target)
+ throws Exception {
+
+ Class<?> beanType = null;
+ if (def.getType() != null) {
+ beanType =
getCamelContext().getClassResolver().resolveClass(def.getType());
+ }
+ if (beanType == null) {
+ beanType = Object.class;
+ }
+
+ // unbind in case we reload
+ getCamelContext().getRegistry().unbind(name);
+ getCamelContext().getRegistry().bind(name, beanType, target,
def.getInitMethod(), def.getDestroyMethod());
+
+ // register bean in model
+ Model model =
getCamelContext().getCamelContextExtension().getContextPlugin(Model.class);
+ model.addCustomBean(def);
+ }
+
}
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java
index aebec90986f..a5a53eded9d 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java
@@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
import org.apache.camel.CamelContext;
import org.apache.camel.dsl.yaml.common.YamlDeserializationContext;
@@ -28,10 +30,12 @@ import
org.apache.camel.dsl.yaml.common.YamlDeserializerSupport;
import org.apache.camel.model.BeanFactoryDefinition;
import org.apache.camel.model.BeanModelHelper;
import org.apache.camel.model.Model;
+import org.apache.camel.spi.CamelBeanPostProcessor;
import org.apache.camel.spi.CamelContextCustomizer;
import org.apache.camel.spi.annotations.YamlIn;
import org.apache.camel.spi.annotations.YamlProperty;
import org.apache.camel.spi.annotations.YamlType;
+import org.apache.camel.support.PluginHelper;
import org.apache.camel.util.ObjectHelper;
import org.snakeyaml.engine.v2.api.ConstructNode;
import org.snakeyaml.engine.v2.nodes.Node;
@@ -96,11 +100,25 @@ public class BeansDeserializer extends
YamlDeserializerSupport implements Constr
List<BeanFactoryDefinition<?>> delayedRegistrations,
BeanFactoryDefinition<?> def, boolean delayIfFailed) {
+ CamelBeanPostProcessor cbpp =
PluginHelper.getBeanPostProcessor(camelContext);
+ Predicate<?> lazy = cbpp.getLazyBeanStrategy();
+
String name = def.getName();
String type = def.getType();
try {
- Object target = BeanModelHelper.newInstance(def, camelContext);
- bindBean(camelContext, def, name, target);
+ // only do lazy bean on 2nd pass as 1st pass may work
+ if (!delayIfFailed && lazy != null && lazy.test(null)) {
+ bindLazyBean(camelContext, def, name, () -> {
+ try {
+ return BeanModelHelper.newInstance(def, camelContext);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ } else {
+ Object target = BeanModelHelper.newInstance(def, camelContext);
+ bindBean(camelContext, def, name, target);
+ }
} catch (Exception e) {
if (delayIfFailed) {
delayedRegistrations.add(def);
@@ -150,4 +168,26 @@ public class BeansDeserializer extends
YamlDeserializerSupport implements Constr
model.addCustomBean(def);
}
+ protected void bindLazyBean(
+ CamelContext camelContext, BeanFactoryDefinition<?> def,
+ String name, Supplier<Object> target)
+ throws Exception {
+
+ Class<?> beanType = null;
+ if (def.getType() != null) {
+ beanType =
camelContext.getClassResolver().resolveClass(def.getType());
+ }
+ if (beanType == null) {
+ beanType = Object.class;
+ }
+
+ // unbind in case we reload
+ camelContext.getRegistry().unbind(name);
+ camelContext.getRegistry().bind(name, beanType, target,
def.getInitMethod(), def.getDestroyMethod());
+
+ // register bean in model
+ Model model =
camelContext.getCamelContextExtension().getContextPlugin(Model.class);
+ model.addCustomBean(def);
+ }
+
}