I keep getting this message that Spring will override MY factory bean definition with the CassandraRepositoryFactoryBean. This is causing problems as the reason I am overriding the factory is to override the save method on a repo so that I can automatically populate createTimestamp and updateTimestamp methods.
2018-01-16 18:24:32,355 INFO main o.s.b.f.s.DefaultListableBeanFactory:828 - Overriding bean definition for bean 'containerIdRepo' with a different definition: replacing [Root bean: class [com.database.repo.audit.TimestampCrudRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Root bean: class [org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
Obviously there is either some order of precedence or missing configuration here but I can't find it. Perhaps you can?
My Spring Configuration:
#Configuration
#EnableCassandraRepositories(repositoryFactoryBeanClass = TimestampCrudRepositoryFactoryBean.class, repositoryBaseClass = TimestampCrudRepositoryImpl.class, basePackages = {
"com.database.repo", "com.database.entity" })
public class DataCassandraConfiguration extends CassandraConfiguration {
#Bean
#Primary
#Order(Ordered.HIGHEST_PRECEDENCE)
public CassandraTemplate cassandraTemplate(Session session, CassandraConverter converter) {
return new CassandraTemplate(session, converter);
}
}
Where I override the TypedIdCassandraRepository
#NoRepositoryBean
public interface TimestampCrudRepository<T extends BaseTimestampEntity, I extends Serializable>
extends TypedIdCassandraRepository<T, I> {
}
If you're curious about the BaseTimestampEntity
public abstract class BaseTimestampEntity {
#CreatedDate
#Column("create_timestamp") // timestamp,
private Instant createTimestamp;
#LastModifiedDate
#Column("update_timestamp") // timestamp,
private Instant updateTimestamp;
}
Where I implement the save method:
#NoRepositoryBean
#Slf4j
public class TimestampCrudRepositoryImpl<T extends BaseAuditEntity, I extends Serializable>
extends SimpleCassandraRepository<T, I> implements TimestampCrudRepository<T, I> {
private final boolean isPrimaryKeyEntity;
public TimeStampCrudRepositoryImpl(CassandraEntityInformation<T, I> metadata, CassandraOperations operations) {
super(metadata, operations);
this.isPrimaryKeyEntity = metadata.isPrimaryKeyEntity();
}
#Override
public <S extends T> S save(S entity) {
log.info("Using overriden save method to add create and update timestamp");
Assert.notNull(entity, "Entity must not be null");
Instant now = Instant.now();
entity.setUpdateTimestamp(now);
if (entity.getCreateTimestamp() == null) {
entity.setCreateTimestamp(now);
}
if (entityInformation.isNew(entity) || isPrimaryKeyEntity) {
return operations.insert(entity);
}
return operations.update(entity);
}
}
And finally my factory:
public class TimestampCrudRepositoryFactoryBean<T extends TimestampCrudRepository<S, I>, S extends BaseTimestampEntity, I extends Serializable>
extends RepositoryFactoryBeanSupport<T, S, I> {
#Autowired
private CassandraTemplate cassandraTemplate;
protected TimestampCrudRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
public void setCassandraTemplate(CassandraTemplate cassandraTemplate) {
this.cassandraTemplate = cassandraTemplate;
}
#Override
protected RepositoryFactorySupport createRepositoryFactory() {
return new TimestampCrudRepositoryFactory(cassandraTemplate);
}
#Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
Preconditions.checkNotNull(cassandraTemplate, "cassandraTemplate must not be null!");
setMappingContext(cassandraTemplate.getConverter().getMappingContext());
}
private static class TimestampCrudRepositoryFactory<S extends BaseAuditEntity, I extends Serializable>
extends CassandraRepositoryFactory {
private final CassandraTemplate cassandraTemplate;
public TimestampCrudRepositoryFactory(CassandraTemplate cassandraTemplate) {
super(cassandraTemplate);
this.cassandraTemplate = cassandraTemplate;
}
#Override
#SuppressWarnings("unchecked")
protected Object getTargetRepository(RepositoryInformation information) {
CassandraEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
return new TimestampCrudRepositoryImpl(entityInformation, cassandraTemplate);
}
#Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return TimestampCrudRepositoryImpl.class;
}
}
}
Almost forgot the repo:
public interface ContainerIdRepo extends TimestampCrudRepository<ContainerEntity, MapId> {}
Nothing is bombing out but the updateTimestamp and createTimestamp inserts into the Cassandra DB are null and I can tell the override save method is not being hit when debugging.
Turns out
#EnableCassandraRepositories(repositoryFactoryBeanClass = TimestampCrudRepositoryFactoryBean.class, repositoryBaseClass = TimestampCrudRepositoryImpl.class, basePackages = {
"com.database.repo", "com.database.entity" })
and
#Bean
#Primary
#Order(Ordered.HIGHEST_PRECEDENCE)
public CassandraTemplate cassandraTemplate(Session session, CassandraConverter converter) {
return new CassandraTemplate(session, converter);
}
Can't live in a separate configuration java class even though the class is annotated with #Configuration. I had to put it in the main application class.
Additionally I had to just delete the factory I created. The TimestampCrudRepositoryFactoryBean
With just the interface and the implementation (and once the annotation was moved) it just worked and Spring didn't try and replace my definition with the more generic one.
Figure it was an order of operations thing with Spring config. At least that's my educated guess.
Related
I have a web app that was built with Spring Data 1.6.1.RELEASE. It adds custom behavior too all repositories by following the example in the Spring Data' online documentation here:
1.3.2 Adding custom behavior to all repositories
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
Basically, it extends JpaRepository with custom behavior shown below:
public interface MyRepository<T, ID extends Serializable>
extends JpaRepository<T, ID> {
void sharedCustomMethod(ID id);
}
Here is the code for implementation of this new interface:
public class MyRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {
private EntityManager entityManager;
public MyRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.entityManager = entityManager;
}
public void sharedCustomMethod(ID id) {
// implementation goes here
}
}
Custom repository factory bean:
public class MyRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
extends JpaRepositoryFactoryBean<R, T, I> {
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new MyRepositoryFactory(entityManager);
}
private static class MyRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {
private EntityManager entityManager;
public MyRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new MyRepositoryImpl<T, I>((Class<T>) metadata.getDomainClass(), entityManager);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
//to check for QueryDslJpaRepository's which is out of scope.
return MyRepository.class;
}
}
}
Here is the declaration of the factory bean:
<repositories base-package="com.acme.repository"
factory-class="com.acme.MyRepositoryFactoryBean" />
Everything works well with Spring Data 1.6.1.RELEASE. However, I got the following exception when starting Jetty in Eclipse after I switched to Spring Data 2.3.2.RELEASE:
java.lang.IllegalStateException: No suitable constructor found on interface com.acme.repository.MyRepository to match the given arguments: [class org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation, class com.sun.proxy.$Proxy52]. Make sure you implement a constructor taking these
at org.springframework.data.repository.core.support.RepositoryFactorySupport.lambda$getTargetRepositoryViaReflection$4(RepositoryFactorySupport.java:522)
at java.util.Optional.orElseThrow(Optional.java:290)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepositoryViaReflection(RepositoryFactorySupport.java:522)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepositoryViaReflection(RepositoryFactorySupport.java:506)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:180)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:162)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:72)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:309)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:212)
at org.springframework.data.util.Lazy.get(Lazy.java:94)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:144)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1790)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:878)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:401)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:292)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:843)
at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:533)
at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:816)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:345)
at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1406)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1368)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:778)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:262)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:522)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
at org.eclipse.jetty.server.Server.start(Server.java:427)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
at org.eclipse.jetty.server.Server.doStart(Server.java:394)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at net.sourceforge.eclipsejetty.starter.jetty9.Jetty9Adapter.start(Jetty9Adapter.java:68)
at net.sourceforge.eclipsejetty.starter.common.AbstractJettyLauncherMain.launch(AbstractJettyLauncherMain.java:84)
at net.sourceforge.eclipsejetty.starter.jetty9.Jetty9LauncherMain.main(Jetty9LauncherMain.java:42)
What can I try to fix this?
UPDATE
I added the following constructor but still have the same problem:
public MyRepositoryImpl(
JpaMetamodelEntityInformation<T, ID> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
this.em = entityManager;
}
I just setup an application with 2.3.2.RELEASE and its look like it has been simplified.
Delete MyRepositoryFactoryBean
Replace <repositories base-package="com.acme.repository... with
<repositories base-package="com.acme.repository"
base-class="….MyRepositoryImpl" />
MyRepositoryImpl
public class MyRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {
private EntityManager entityManager;
MyRepositoryImpl(JpaEntityInformation entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
// Keep the EntityManager around to used from the newly introduced
this.entityManager = entityManager;
}
public void sharedCustomMethod(ID id) {
// implementation goes here
}
}
Make sure MyRepository is outside the package base-package i.e com.acme.repository.
Note
#EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class) on a class annotated #Configuration is equivalent to point 2. As long as the package of that configuration class is com.acme.repository
#NoRepositoryBean annotation on MyRepository is equivalent to point 4
Sample Spring boot app with java config for reference
https://github.com/kavi-kanap/stackoveflow-63223076
Import it as maven project to your IDE. Right click on AccessingDataJpaApplication and run, it will start, save some entities and call your custom method
I saw a method of using #inject annotation with parameter constructor. I found no use in #module in all parts of the project. I don't understand how this code injects or provides parameters in the constructor.
Can you help me analyze it?
Where is the datamanager provided?
In the whole project, #module + #provide is not used to provide datamanager. I only know that #inject can only annotate the parameterless constructor. I don't know where to instantiate the parameterless datamanager object. Thank you for your help
application:
public class Scallop extends Application {
private ApplicationComponent applicationComponent;
#Override
public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
}
public ApplicationComponent getApplicationComponent() {
return applicationComponent;
}
}
application module:
#Module
public class ApplicationModule {
private Scallop application;
public ApplicationModule(Scallop application) { // 提供类的构造器,传入Applicaton
this.application = application;
}
#Provides
#Singleton
Application provideApplication() {
return application;
}
#Provides
#ApplicationContext
Context provideContext() {
return application;
}
#Provides
#Singleton
Retrofit provideRetrofit() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return retrofit;
}
#Provides
#Singleton
GankIOService provideGankIOService(Retrofit retrofit) {
return retrofit.create(GankIOService.class);
}
}
#Singleton
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
Application getApplication();
DataManager getDataManager();
}
```
one class:
#Singleton
public class DataManager {
private GankIOService gankIOService;
private PreferencesHelper preferencesHelper;
#Inject
public DataManager(GankIOService gankIOService, PreferencesHelper preferencesHelper) {
this.gankIOService = gankIOService;
this.preferencesHelper = preferencesHelper;
}
}
fragment module:
#FragmentScope
#Component(modules = FragmentModule.class, dependencies = ApplicationComponent.class)
public interface FragmentComponent {
void inject(HomeFragment homeFragment);
void inject(GanHuoPageFragment pageFragment);
void inject(XianDuFragment xianDuFragment);
void inject(XianDuPageFragment xianDuPageFragment);
void inject(PicturesFragment picturesFragment);
void inject(MoreFragment moreFragment);
}
#FragmentScope
#Documented
#Scope
#Retention(value = RetentionPolicy.RUNTIME)
public #interface FragmentScope {
}
```
here Can't understand constructor with parameter is #inject
public class GanHuoPagePresenter extends BasePresenter<GanHuoPageContract.View>
implements GanHuoPageContract.Presenter {
private DataManager dataManager;
private Disposable disposable;
#Inject
public GanHuoPagePresenter(DataManager dataManager) { // here here
this.dataManager = dataManager;
}
#Override
public void detachView() {
super.detachView();
if (disposable != null) {
disposable.dispose();
}
}
#Override
public void getGanHuo(String category, final int page) {
final List<GanHuo> ganHuoList = new ArrayList<>();
Observable<BaseResponse<GanHuo>> observable = dataManager.getGanHuo(category, page);
disposable = observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.concatMap(new Function<BaseResponse<GanHuo>, ObservableSource<GanHuo>>() {
#Override
public ObservableSource<GanHuo> apply(#NonNull BaseResponse<GanHuo> ganHuoBaseResponse)
throws Exception {
return Observable.fromIterable(ganHuoBaseResponse.getResults());
}
}).filter(new Predicate<GanHuo>() {
#Override
public boolean test(#NonNull GanHuo ganHuo) throws Exception {
return !ganHuo.getType().equals("福利");
}
}).subscribe(new Consumer<GanHuo>() {
#Override
public void accept(GanHuo ganHuo) throws Exception {
ganHuoList.add(ganHuo);
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
getView().showError(throwable.getMessage());
}
}, new Action() {
#Override`enter code here`
public void run() throws Exception {
getView().showList(ganHuoList, page);
}
});
}
}
This is how it is used in V in MVP mode:
#Inject GanHuoPagePresenter presenter
That's constructor injection. By marking a constructor with #Inject Dagger knows about the object and can create it when needed. There's no need for modules, e.g. the following is a valid Dagger setup to create some Foo.
public class Foo {
#Inject
public Foo() {}
}
#Component
interface MyComponent {
Foo getFoo();
}
That's not true that #Inject can only annotate the parameterless constructor. From documentation
Injectable constructors are annotated with #Inject and accept zero or more dependencies as arguments.
I found "your" project on Github so let's see where dependencies for GanHuoPagePresenter come from.
#Inject
public GanHuoPagePresenter(DataManager dataManager) {
this.dataManager = dataManager;
}
#Inject
public DataManager(GankIOService gankIOService,PreferencesHelper preferencesHelper){
// gankIOService is provided by ApplicationModule and preferencesHelper uses constructor injection
this.gankIOService = gankIOService;
this.preferencesHelper = preferencesHelper;
}
#Inject
public PreferencesHelper(#ApplicationContext Context context){
// context is provided again by ApplicationModule
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
}
I have a chain of Features. I would like to bind some beans inside ConfigFeature and then get them inside the MongoDBFeature. What methods should I use for that?
public final class IoCBinder extends AbstractBinder {
#Override
protected void configure() {
ConfigFeature.configureIoC(this);
MongoDBFeature.configureIoC(this);
}
}
Put some bean here:
public class ConfigFeature {
public static void configureIoC(AbstractBinder binder) {
// ....
binder.bind(configProvider).to(ConfigurationProvider.class).in(Singleton.class).named("configProvider");
}
}
And I would like to get configProvider bean here:
public class MongoDBFeature {
public static void configureIoC(AbstractBinder binder) {
// ?? get configProvider here ??
}
}
You can bind your bean to the ServiceLocator as shown in below example.
Service
public class TestService{
}
Binder
public static TestBinder extends AbstractBinder{
#Override
protected void configure() {
bind(new TestService()).to(TestService.class);
}
}
Feature 1
public class Feature1 implements Feature{
#Inject
private ServiceLocator locator;
#Override
public boolean configure(FeatureContext context) {
org.glassfish.hk2.utilities.ServiceLocatorUtilities.bind(locator,new TestBinder());
return true;
}
}
Note that a ServiceLocator instance is injected to Feature1 and the binder is bound to this locator instance.
Feature 2
public class Feature2 implements Feature{
#Inject
private TestService testService;
#Override
public boolean configure(FeatureContext context) {
return true;
}
}
Application/ResourceConfig class
public class TestConfig extends ResourceConfig {
register(Feature1.class);
// Need to make sure Feature1 is registered before Feature2.
// Another option is to register Feature2 in configure() method of Feature1 class.
register(Feature2.class);
}
When trying to override SimpleJpaRepository, adding other beans via #Autowired does not work. How can beans be injected in this case? Here is an implementation:
public class BaseDAO<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID>
implements IDAO<T, ID> {
#Autowired
private SomeBean someBean; // NULL!
}
Instances of BaseDAO are not Spring-managed beans in themselves and therefore autowiring through #Autowired will not work out-of-the-box. Dependencies therefore need to be injected into BaseDAO instances.
Step 1: Have a Spring ApplicationContext available somewhere
#Component
class SpringContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(final ApplicationContext context) throws BeansException {
CONTEXT = context;
}
public static ApplicationContext getContext() { return CONTEXT; }
}
This will be required to autowire the dependencies for the custom repository implementation at the time of repository creation.
Step 2: Extend SimpleJpaRepository
class BaseDAO<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> {
#Autowired
private Dependency dependency;
}
Step 3: Autowire dependencies through a JpaRepositoryFactoryBean
class ExtendedJPARepositoryFactoryBean<R extends JpaRepository<T, ID>, T, ID extends Serializable>
extends JpaRepositoryFactoryBean<R, T, ID> {
private static class ExtendedJPARepositoryFactory<T, ID extends Serializable> extends JpaRepositoryFactory {
public ExtendedJPARepositoryFactory(final EntityManager entityManager) {
super(entityManager);
}
protected Class<?> getRepositoryBaseClass(final RepositoryMetadata metadata) {
return isQueryDslExecutor(metadata.getRepositoryInterface())
? QueryDSLJPARepository.class
// Let your implementation be used instead of SimpleJpaRepository.
: BaseDAO.class;
}
protected <T, ID extends Serializable> SimpleJpaRepository<?, ?> getTargetRepository(
RepositoryInformation information, EntityManager entityManager) {
// Let the base class create the repository.
final SimpleJpaRepository<?, ?> repository = super.getTargetRepository(information, entityManager);
// Autowire dependencies, as needed.
SpringContext.getContext()
.getAutowireCapableBeanFactory()
.autowireBean(repository);
// Return the fully set up repository.
return repository;
}
}
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new ExtendedJPARepositoryFactory(entityManager);
}
}
Step 4a: Configure Spring Data JPA to use your factory bean (XML configuration)
<jpa:repositories base-package="org.example.jpa"
factory-class="org.example.jpa.ExtendedJPARepositoryFactoryBean"/>
Step 4b: Configure Spring Data JPA to use your factory bean (Java configuration)
#EnableJpaRepositories(repositoryFactoryBeanClass = ExtendedJPARepositoryFactoryBean.class)
In order to let Spring know that it needs to inject something inside your DAO you need to annotate it with #Component.
You can read more about this here: http://docs.spring.io/autorepo/docs/spring-boot/current/reference/html/using-boot-spring-beans-and-dependency-injection.html.
When i try to send a request that uses a ValueProxy params i'm getting this 'Unforzen bean' exception. I don't know if this exception is because a bug with RF using JsonDialect or i'm doing something wrong... ¿Some help?
java.lang.AssertionError: Unfrozen bean with null RequestContext
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.checkStreamsNotCrossed(AbstractRequestContext.java:981)
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.editProxy(AbstractRequestContext.java:509)
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.edit(AbstractRequestContext.java:502)
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.retainArg(AbstractRequestContext.java:1230)
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.access$2(AbstractRequestContext.java:1223)
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$JsonRpcPayloadDialect.addInvocation(AbstractRequestContext.java:202)
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.addInvocation(AbstractRequestContext.java:661)
at es.xxxx.taller.client.Taller_SomeRequestContextImpl.SomeCall(Taller_SomeRequestContextImpl.java:29)
at es.xxxx.taller.client.Taller.onModuleLoad(Taller.java:417)
public class SomeEntryPoint implements EntryPoint {
#JsonRpcProxy
public interface SomeProxy extends ValueProxy {
String getSomeProperty();
void setSomeProperty(String value);
}
#JsonRpcProxy
public interface VoidProxy extends ValueProxy {
}
public interface SomeAutoBeanFactory extends AutoBeanFactory {
SomeAutoBeanFactory INSTANCE = GWT.create(SomeAutoBeanFactory.class);
AutoBean<SomeProxy> someProxy();
}
public interface SomeRequestFactory extends RequestFactory {
SomeRequestFactory INSTANCE = GWT.create(SomeRequestFactory.class);
SomeRequestContext context();
}
#JsonRpcService
public interface SomeRequestContext extends RequestContext {
SomeCall SomeCall(SomeProxy proxy);
#JsonRpcWireName(value = "SomeCall")
public interface SomeCall extends Request<VoidProxy> {
}
}
public void onModuleLoad() {
SomeProxy someProxy = SomeAutoBeanFactory.INSTANCE.someProxy().as();
someProxy.setSomeProperty("someValue");
SomeRequestFactory.INSTANCE.context().SomeCall(someProxy).fire();
}
}
Proxies should be created by a RequestContext, not an AutoBeanFactory! Using the JsonRpc dialect doesn't change how you use RequestFactory.
public void onModuleLoad() {
SomeRequestContext ctx = SomeRequestFactory.INSTANCE.context();
SomeProxy someProxy = ctx.create(SomeProxy.class);
someProxy.setSomeProperty("someValue");
ctx.SomeCall(someProxy).fire();
}