问题描述。
这是immutables站点中当前示例的简化版本。
所以我有一个项目,我想使用MongoDB。
@Value.Immutable
@Mongo.Repository("items")
public abstract class Item {
@Mongo.Id
public abstract long id();
public abstract String name();
}
为了简单起见,我创建了一个Junit测试。就像这个例子。问题是,这个junit测试在immutables站点的示例中出现时引发了一个异常:
public class ItemTest{
@Test
public void testRepository() {
try {
//Simple ItemRepository creation
ItemRepository items = new ItemRepository(
RepositorySetup.forUri("mongodb://localhost/test")
);
// Create item Item item = ImmutableItem.builder()
.id(1)
.name("one")
.build();
//Insert is async. Returns a Future.
FluentFuture<Integer> future=items.insert(item);
future.get(); // get the result (ensure it was saved)
}catch(Exception e){
e.printStackTrace();
Assert.fail(e.getMessage());
}
}//end test
}//end class
运行此测试将导致以下异常:
org.bson.codecs.configuration.代码配置异常:找不到接口spyros.stackoverflow.example.项的编解码器
下面提供了完整的堆栈跟踪。
java.lang.AssertionError: java.util.concurrent.ExecutionException: **org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for interface spyros.stackoverflow.example.Item.**
at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:552)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:533)
at com.google.common.util.concurrent.FluentFuture$TrustedFuture.get(FluentFuture.java:82)
at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture.java:62)
at spyros.stackoverflow.example.ItemTest.testRepository(ItemTest.java:78)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for interface spyros.stackoverflow.example.Item.
at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
at com.mongodb.MongoCollectionImpl.getCodec(MongoCollectionImpl.java:591)
at com.mongodb.MongoCollectionImpl.insertMany(MongoCollectionImpl.java:333)
at com.mongodb.MongoCollectionImpl.insertMany(MongoCollectionImpl.java:322)
at org.immutables.mongo.repository.Repositories$Repository$2.call(Repositories.java:130)
at org.immutables.mongo.repository.Repositories$Repository$2.call(Repositories.java:127)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:125)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:69)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
at org.junit.Assert.fail(Assert.java:88)
at spyros.stackoverflow.example.ItemTest.testRepository(ItemTest.java:84)
我使用gradle和构建。gradle
如下所示。
plugins {
id 'java'
id 'java-library'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.7'
implementation 'org.apache.logging.log4j:log4j-core:2.7'
implementation 'javax.persistence:javax.persistence-api:2.2'
implementation 'javax.xml.bind:jaxb-api:2.1'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
implementation 'com.google.guava:guava:27.1-jre'
annotationProcessor 'org.immutables:value:2.7.4'
implementation 'org.immutables:value:2.7.4'
implementation 'org.immutables:mongo:2.7.4'
implementation 'org.apache.commons:commons-lang3:3.4'
implementation 'org.apache.commons:commons-collections4:4.1'
implementation 'org.apache.commons:commons-configuration2:2.3'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
查明原因
Immutables JSON库需要能够找到自动生成的GsonAdaptersItem。类
实现com.google.格森。TypeAdapterFactory
。事实上,对于每个名为XXX
的接口
或抽象类
,具有与“类项”(如上所述)类似的注释,不可变项将生成一个类似的GsonAdapterXXX
,该实现com.google.格森。TypeAdapterFactory
为了能够自动找到这些类,
RepositorySetup
使用java。util。ServiceLoader
来自动定位它们。这是相关的代码部分:
GsonBuilder gsonBuilder = new GsonBuilder();
// there are no longer auto-registed from class-path, but from here or if added manually.
gsonBuilder.registerTypeAdapterFactory(new TypeAdapters());
for (TypeAdapterFactory factory : ServiceLoader.load(TypeAdapterFactory.class)) {
gsonBuilder.registerTypeAdapterFactory(factory);
}
return gsonBuilder.create();
引发异常的原因是,由于某种原因,这似乎不起作用,因此引发了以下异常。
UPDATE进一步的研究表明,这个例子是有效的,但前提是jar已经编译过了。这是因为不可变生成以下文件,该文件实际上将用于查找所有必需的
GsonAdapterXXX
类。
build\classes\java\main\META-INF\services\com.google.gson.TypeAdapterFactory
组织。布森。编解码器。配置CodeConfigurationException:找不到接口spyros的编解码器。堆栈溢出。实例这是源代码的永久链接。
工作方法简单明了的工作方法是将
GsonAdaptersItem
专门注册到GsonBuilder
中。下面的JUnit测试可以工作。
@Test
public void testItemVerbose() {
try {
//repeat what the RepositorySetup#createGson does
GsonBuilder gsonBuilder = new GsonBuilder();
//iterating in this loop
for (TypeAdapterFactory factory : ServiceLoader.load(TypeAdapterFactory.class)) {
//You can see that the ServiceLoader does not find the GsonAdaptersItem
//System.out.println("Factory:"+factory.getClass().getCanonicalName()+" "+factory.toString());
gsonBuilder.registerTypeAdapterFactory(factory);
}
//add the GsonAdaptersItem manually
gsonBuilder.registerTypeAdapterFactory(new GsonAdaptersItem());
Gson gson = gsonBuilder.create();
Item item = ImmutableItem.builder()
.id(1)
.name("one")
.build();
final MongoClient mongo = new MongoClient( "localhost" , 27017 );
final MongoDatabase mongoDatabase=mongo.getDatabase("test");
ItemRepository items =new ItemRepository(
RepositorySetup.builder()
.executor(MoreExecutors.newDirectExecutorService())
.database(mongoDatabase)
.gson(gson).build()
);
// Insert async and get
items.insert(item).get(); // returns future, works
}catch (final Exception e){
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
此解决方法可用于手动创建通用api,程序员需要提供
GsonAdapterXXX
。例如,ItemRepository ItemRepository=reporitoryProvider。getRepositoryWithRegisteredGsonAdapter(新的GsonAdaptersItem())
更具体的
XXXRepository
提供程序。
public ItemRepository getItemRepository(){
return reporitoryProvider.getRepositoryWithRegisteredGsonAdapter(new GsonAdaptersItem());
}
然而,所有这些都需要维护,更容易出错,而且无论如何都需要编写样板代码,这是使用Immutables的人希望避免的。
问题
我希望这个例子可以像immutables网站所示那样工作。我最好的猜测是,既然我使用gradle而不是maven,也许我需要更改一些设置或依赖项。问题是:为了使简单的ItemRepository创建(如下所示)工作,需要做哪些更改?
//Simple ItemRepository creation
ItemRepository items = new ItemRepository(
RepositorySetup.forUri("mongodb://localhost/test")
);
有没有可能在不可变的情况下,不用手动编写代码来逐类或逐包注册编解码器?我真的很想知道为什么它一开始就不起作用。
过了一段时间,我又重新问这个老问题。目前建议的解决方案是使用immutables的criteria功能。
@Value.Immutable
@Criteria.Repository
public abstract class Item {
@Criteria.Id
public abstract long id();
public abstract String name();
}
我读过这段代码,其中接口抛出异常,但实现它的类没有抛出异常或捕获异常,这是为什么?它在java中是合法的还是安全的?
我正在尝试为一个简单的web应用程序创建一个存储库。似乎导入和使用导入组织。springframework。数据存储库。积垢会导致错误。我不确定如何开始调试收到的错误消息。 这是我的实体 这是我的存储库 这是我的控制器 还有我的pom.xml
我创建了一个简单应用程序,它使用Spring boot和JPA/Hibernate将消息保存在postgresql数据库中。所有的包Controller/Service/Repository都在一个子包中。 但我得到一个错误:spring boot无法识别包DAO中的存储库接口。 我有另一个项目,所有工作都不使用@enablejparepositories,但在这个项目(相同的结构)中,我遇到了这
我有一个简单的类叫做Signal。课程内容如下: 我试图在MongoDB(v3.4)插入信号。我使用以下方法插入: 我得到了以下例外: org.bson.codecs.configuration.代码配置异常:找不到in.co.mysite.webapi.models.Signal类的编解码器。 我在这里检查了一个类似的问题,但是插入代码不同。我从回答中得到提示,修改了我的方法,但看起来不干净。修
我试图从方法中抛出异常,但当我编译下面的代码时 编译错误 发射装置。java:14:错误:找不到符号静态void getError()抛出^myException{ 符号:类myException 位置:类启动器 它说了些什么,它无法理解什么是