I've written a simple RestEasy client proxy to perform an iTunes search. It looks like this:
#Path("/")
public interface AppleAppStoreLookupClient {
/**
* Attempts to lookup an apple app store item by its ID
*
* #param id
* The item ID
* #return The app details
*/
#GET
#Path("/lookup")
#Produces(value = { "text/javascript" })
public AppleAppDetailsResponse lookupByID(#QueryParam("id") String id);
}
My JSON model class is simple, as well. In fact, for the first call all I want is the "resultCount" value, just to make sure connectivity works.
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
public class AppleAppDetailsResponse implements Serializable {
private static final long serialVersionUID = 8881587082097337598L;
#XmlElement
private int resultCount = -1;
...getters and setters...
}
However, when I run a simple test, I get the following Exception:
org.jboss.resteasy.client.ClientResponseFailure: Unable to find a MessageBodyReader of content-type text/javascript;charset="utf-8" and type class net.odyssi.mms.appstore.apple.AppleAppDetailsResponse
at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:523)
at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:514)
at org.jboss.resteasy.client.core.BaseClientResponse.readFrom(BaseClientResponse.java:415)
at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:377)
at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:350)
at org.jboss.resteasy.client.core.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:62)
at org.jboss.resteasy.client.core.ClientInvoker.invoke(ClientInvoker.java:126)
at org.jboss.resteasy.client.core.ClientProxy.invoke(ClientProxy.java:88)
at $Proxy21.lookupByID(Unknown Source)
at net.odyssi.mms.appstore.apple.test.AppleAppStoreLookupClientTest.testLookupByID(AppleAppStoreLookupClientTest.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I'm running RestEasy 2.3.6. Any idea what could be causing such an error?
Do you have a json provider on your classpath? If you are using maven, try adding this dependency:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jettison-provider</artifactId>
<version>2.3.6.Final</version>
</dependency>
http://docs.jboss.org/resteasy/docs/2.3.6.Final/userguide/html_single/#JAXB_+_JSON_provider
EDIT:
Normally, one would use the content type application/json and not text/javascript. I'm not sure why you are using text/javascript?
Anyways, if your endpoint returns only text/javascript, you can always modify the Content-Type-header in an interceptor:
ResteasyProviderFactory factory = new ResteasyProviderFactory();
RegisterBuiltin.register(factory);
factory.getClientExecutionInterceptorRegistry().register(
new ClientExecutionInterceptor() {
#Override
public ClientResponse execute(ClientExecutionContext ctx) throws Exception {
ClientResponse response = ctx.proceed();
if("text/javascript".equals(response.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE))){
response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
}
return response;
}
});
ProxyFactory.create(Service.class, URI.create("http://url-to-your-sevice"), new ApacheHttpClient4Executor(), factory);
Related
I have a requirement where I read a file with different kinds of input as below:
*JAMBEG,APP=000007,123456
AC,654321,“ABCD12121212121212”,23423423423424234,ABCDD,23423423423424234,2424,XYZ,ABC,TREX,000000002
AC,654321,“ABCD12121212121213”,23423423423424234,ABCDD,23423423423424234,2424,XYZ,ABC, TREX,000000002
...
AC,654321,“ABCD12121212121214”,23423423423424234,ABCDD,23423423423424234,2424,XYZ,ABC, TREX,000000002
*JAMEND,APP=000007,123456
EOF
I need only the Header line and the records following that, ignoring the line that starts with TREX, *JAMEND, EOF.
Here is how my line mapper is:
public LineMapper<Customer> lineMapper(){
DelimitedLineTokenizer lineTokenizerHeader = new DelimitedLineTokenizer();
lineTokenizerHeader.setNames(new String[]{"association","companyNumber","fileDate"});
lineTokenizerHeader.setIncludedFields(new int[]{0,1,2});
lineTokenizerHeader.setStrict(false);
DelimitedLineTokenizer lineTokenizerBody = new DelimitedLineTokenizer();
lineTokenizerBody.setNames(new String[]{"type","acNumber","orderNumber"});
lineTokenizerBody.setIncludedFields(new int[]{0,1,2});
lineTokenizerBody.setStrict(false);
HashMap<String, DelimitedLineTokenizer> tokenizers = new HashMap<String, DelimitedLineTokenizer>();
tokenizers.put("*BEG*", lineTokenizerHeader);
tokenizers.put("AC*", lineTokenizerBody);
BeanWrapperFieldSetMapper<Customer> beanWrapperFieldSetMapper = new BeanWrapperFieldSetMapper<Customer>();
beanWrapperFieldSetMapper.setTargetType(Customer.class);
beanWrapperFieldSetMapper.setStrict(false);
HashMap<String, BeanWrapperFieldSetMapper<Customer>> fieldSetMappers = new HashMap<String, BeanWrapperFieldSetMapper<Customer>>();
fieldSetMappers.put("*BEG*", beanWrapperFieldSetMapper);
fieldSetMappers.put("AC*", beanWrapperFieldSetMapper);
PatternMatchingCompositeLineMapper patternMatchingCompositeLineMapper = new PatternMatchingCompositeLineMapper();
patternMatchingCompositeLineMapper.setTokenizers(tokenizers);
patternMatchingCompositeLineMapper.setFieldSetMappers(fieldSetMappers);
return patternMatchingCompositeLineMapper;
}
Its my obvious mistake that I don't have any mapping for TREX, *JAMEND, EOF patterns. Hence it throws the below exception:
2014-06-16 16:49:34,746 [main] DEBUG
org.springframework.batch.core.step.item.FaultTolerantChunkProvider -
Parsing error at line: 5 in resource=[class path resource
[0000123456.csv]], input=[EOF] :
org.springframework.batch.item.file.FlatFileParseException 2014-06-16
16:49:34,746 [main] DEBUG
org.springframework.batch.core.step.item.FaultTolerantChunkProvider -
Skipping failed input
org.springframework.batch.item.file.FlatFileParseException: Parsing
error at line: 5 in resource=[class path resource [0000123456.csv]],
input=[EOF] at
org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:183)
at
org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:83)
at
org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91)
at
org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:87)
at
org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:114)
at
org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at
org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at
org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at
org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:108)
at
org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)
at
org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:402)
at
org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:326)
at
org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at
org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267)
at
org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at
org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at
org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at
org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at
org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
at
org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198)
at
org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at
org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:386)
at
org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135)
at
org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304)
at
org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
at
org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at
org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597) at
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at
org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:117)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy17.run(Unknown Source) at
com.chofac.pm.batch.CustomerFileToDBJobTest.testLaunchJob(CustomerFileToDBJobTest.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597) at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at
org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at
org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at
org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at
org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at
org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at
org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.IllegalStateException: Could not find a matching
pattern for key=[EOF] at
org.springframework.batch.support.PatternMatcher.match(PatternMatcher.java:226)
at
org.springframework.batch.item.file.mapping.PatternMatchingCompositeLineMapper.mapLine(PatternMatchingCompositeLineMapper.java:62)
at
org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:180)
... 67 more
I looked at many examples, this one matched close, and changed my step as below, but still the same issue.
#Bean
public Step step(){
return stepBuilders.get("step")
.<Customer,Customer>chunk(1)
.reader(CustomerAUFileReader())
.faultTolerant()
.skipLimit(3)
.skip(Exception.class)
.processor(CustomerRecordProcessor())
.writer(CustomerDBWriter())
.listener(logProcessListener())
.build();
}
Looked at the Spring.io docs here for skipping records (5.1.5 Configuring Skip Logic), does not work either.
Please let me know the ideal way to get around this issue. Should there not be an easy way to specify skipping records that do not match specific cases? Please advise. Thanks.
---
I have a pattern mapper for '*' which I am mapping with a dummy class. I am returning null at the process stage but its throwing nullpointerexception.
Stack Trace:
2014-06-17 10:03:01,690 [main] DEBUG org.springframework.batch.core.step.item.FaultTolerantChunkProcessor - Skipping after failed process
org.springframework.batch.core.listener.StepListenerFailedException: Error in afterProcess.
at org.springframework.batch.core.listener.MulticasterBatchListener.afterProcess(MulticasterBatchListener.java:136)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:127)
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$1.doWithRetry(FaultTolerantChunkProcessor.java:225)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:263)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:193)
at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:217)
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.transform(FaultTolerantChunkProcessor.java:290)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:192)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:402)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:326)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:386)
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy17.run(Unknown Source)
at com.chofac.pl.batch.CustomerFileToDBJobTest.testLaunchJob(CustomerFileToDBJobTest.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.NullPointerException
at com.chofac.pl.batch.CustomerItemProcessListener.afterProcess(CustomerItemProcessListener.java:13)
at org.springframework.batch.core.listener.CompositeItemProcessListener.afterProcess(CompositeItemProcessListener.java:60)
at org.springframework.batch.core.listener.MulticasterBatchListener.afterProcess(MulticasterBatchListener.java:133)
One approach:
Have your ItemReader simply read a line and return as is. Therefore the items given by the reader will be a simple String.
Write a simple ItemProcessor, which mostly do the work of your LineMapper, base on a pattern for example: if the item matches with a pattern, then translate the input string to your Customer return. If pattern not matching, simply return null and the item will be skipped.
psuedo code for the item processor:
class CustomPatternMatchingItemProcessor<String, Customer>
implements ItemProcessor<String, Customer> {
private String pattern;
public Customer process(String s) {
if (s matches pattern) {
construct Customer object base on s
return customer
} else {
return null;
}
}
}
Or even cleaner: have one processor do the work of mapping from String to Customer, and another processor to do the validation of string base on regex.
just chain your processors using a CompositeItemProcessor. This give a even better separation of concern for each of your processor.
I have a similiar issue, where the file I am sent will always have some lines that don't fit the correct pattern. As I just want to ignore these lines, I log them, and skip them.
You can implement
org.springframework.batch.repeat.exception.ExceptionHandler like such:
class LocalExceptionHandler implements ExceptionHandler {
#Override
public void handleException(RepeatContext rc, Throwable throwable) throws Throwable {
if (throwable instanceof FlatFileParseException) {
FlatFileParseException fe = (FlatFileParseException)throwable;
log.error("!!!! FlatFileParseException, line # is: " + fe.getLineNumber());
log.error("!!!! FlatFileParseException, input is: " + fe.getInput());
}
log.error("!!!! Message : " + throwable.getMessage());
log.error("!!!! Cause : " + throwable.getCause());
}
}
and then add that to your step builder:
faultTolerantStepBuilder.exceptionHandler(new LocalExceptionHandler());
faultTolerantStepBuilder.skipLimit(100);
Your intention is not to skip object due to errors, but skip records with a logic; I think your best option is put a mapper binded to '*' and return a custom object (like a SkippableRecordBean) instead of a Customer and filter out unwanted beans in ItemProcessor.
We started returning Dummy object from the LineMapper instead of null as null causes the reader to skip reading other lines. In the ItemWriter, the write method still gets this dummy object and you need to validate before processing it. We ignore the dummy records in the ItemWriter.
public class FileVerificationSkipper implements SkipPolicy {
#Autowired
private Environment environment;
#Override
public boolean shouldSkip(Throwable exception, int skipCount) throws SkipLimitExceededException {
int skipErrorsRecords = Integer.valueOf(environment.getProperty("max.error.record.count"));
if (exception instanceof FileNotFoundException) {
return false;
} else if (exception instanceof FlatFileParseException && (skipErrorsRecords < 0 || skipCount <= (skipErrorsRecords-1))) {
FlatFileParseException ffpe = (FlatFileParseException) exception;
StringBuilder errorMessage = new StringBuilder();
errorMessage.append((skipCount+1)+", An error occured while processing the " + ffpe.getLineNumber() + " record of the file. the faulty record is:\n");
errorMessage.append(ffpe.getInput() + "\n");
return true;
} else {
return false;
}
}
}
and StepBuilder is:
#Bean
public Step step1() throws Exception{
return stepBuilderFactory.get("step1")
.<User, User> chunk(50)
.reader(reader())
.faultTolerant()
.skipPolicy(fileVerificationSkipper())
.processor(processor())
.writer(writer())
.build();
}
For a REST serives (RESTeasy) I have created JUnit test cases like:
#Test
public void a100_insertAddressTest() throws Exception {
Address addr = new Address(1, "testStreet", "1", (short) 1234,
"testCity");
ClientRequest request = new ClientRequest(BASE_URL + "customerID/{id}",
sslExecutor_schusb);
request.body(MediaType.APPLICATION_XML, addr).pathParameter(
"id", 1);
ClientResponse<String> response = request.post(String.class);
Assert.assertEquals(201, response.getStatus());
response.releaseConnection();
request.clear();
}
If I change the media type of the request body to "application/json", the test case fails with the error:
java.lang.RuntimeException: could not find writer for content-type application/json type: at.fhj.ase.dao.data.Address
at org.jboss.resteasy.client.ClientRequest.writeRequestBody(ClientRequest.java:469)
at org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor.loadHttpMethod(ApacheHttpClient4Executor.java:221)
at org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor.execute(ApacheHttpClient4Executor.java:107)
at org.jboss.resteasy.core.interception.ClientExecutionContextImpl.proceed(ClientExecutionContextImpl.java:39)
at org.jboss.resteasy.plugins.interceptors.encoding.AcceptEncodingGZIPInterceptor.execute(AcceptEncodingGZIPInterceptor.java:40)
at org.jboss.resteasy.core.interception.ClientExecutionContextImpl.proceed(ClientExecutionContextImpl.java:45)
at org.jboss.resteasy.client.ClientRequest.execute(ClientRequest.java:443)
at org.jboss.resteasy.client.ClientRequest.httpMethod(ClientRequest.java:674)
at org.jboss.resteasy.client.ClientRequest.post(ClientRequest.java:565)
at org.jboss.resteasy.client.ClientRequest.post(ClientRequest.java:570)
at at.fhj.ase.business.ServiceAddressImplTest.a100_insertAddressTest(ServiceAddressImplTest.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Hence I created a MessageBodyWriter which works fine if I do a POST request by using the firefox plugin RESTClient:
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class JsonMsbWriter implements MessageBodyWriter<Address> {
#Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
if(type == Address.class){
return true;
}
return false;
}
#Override
public long getSize(Address t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
#Override
public void writeTo(Address t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
ObjectMapper m = new ObjectMapper();
m.writeValue(entityStream, t);
}
}
and updated the JUnit test case to:
#Test
public void a100_insertAddressTest() throws Exception {
Address addr = new Address(1, "testStreet", "1", (short) 1234,
"testCity");
ResteasyProviderFactory fact = ResteasyProviderFactory.getInstance();
fact.addMessageBodyWriter(JsonMsbWriter.class);
ClientRequest request = new ClientRequest(BASE_URL + "customerID/{id}",
sslExecutor_schusb);
request.body(MediaType.APPLICATION_JSON, addr).pathParameter("id", 1);
ClientResponse<String> response = request.post(String.class);
Assert.assertEquals(201, response.getStatus());
response.releaseConnection();
request.clear();
}
But now I get the error:
java.lang.VerifyError: (class: org/codehaus/jackson/map/ObjectMapper, method: writeValueAsBytes signature: (Ljava/lang/Object;)[B) Incompatible argument to function
at at.fhj.ase.xmlvalidation.msbreader.JsonMsbWriter.writeTo(JsonMsbWriter.java:46)
at at.fhj.ase.xmlvalidation.msbreader.JsonMsbWriter.writeTo(JsonMsbWriter.java:1)
at org.jboss.resteasy.core.interception.MessageBodyWriterContextImpl.proceed(MessageBodyWriterContextImpl.java:117)
at org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor.write(GZIPEncodingInterceptor.java:100)
at org.jboss.resteasy.core.interception.MessageBodyWriterContextImpl.proceed(MessageBodyWriterContextImpl.java:123)
at org.jboss.resteasy.client.ClientRequest.writeRequestBody(ClientRequest.java:472)
at org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor.loadHttpMethod(ApacheHttpClient4Executor.java:221)
at org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor.execute(ApacheHttpClient4Executor.java:107)
at org.jboss.resteasy.core.interception.ClientExecutionContextImpl.proceed(ClientExecutionContextImpl.java:39)
at org.jboss.resteasy.plugins.interceptors.encoding.AcceptEncodingGZIPInterceptor.execute(AcceptEncodingGZIPInterceptor.java:40)
at org.jboss.resteasy.core.interception.ClientExecutionContextImpl.proceed(ClientExecutionContextImpl.java:45)
at org.jboss.resteasy.client.ClientRequest.execute(ClientRequest.java:443)
at org.jboss.resteasy.client.ClientRequest.httpMethod(ClientRequest.java:674)
at org.jboss.resteasy.client.ClientRequest.post(ClientRequest.java:565)
at org.jboss.resteasy.client.ClientRequest.post(ClientRequest.java:570)
at at.fhj.ase.business.ServiceAddressImplTest.a100_insertAddressTest(ServiceAddressImplTest.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
How can I attach such a writer for json?
And why does it work for content type application/xml out of the
box?
For GET requests and application/json there is the same problem, however with the reader instead of the writer.
Problem solved, unfortunately I haven't included all necessary 3rd party libraries to the projects build path. Finally I added the following jars:
jackson-core-asl-1.6.3.jar
jackson-jaxrs-1.6.3.jar
jackson-mapper-asl-1.6.3.jar
jackson-xc-1.6.3.jar
resteasy-jackson-provider-2.2.1.GA.jar
This example brings the strength of Maven to the front. With Maven there is only one entry necessary to fulfill these dependencies.
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>2.2.1.GA</version>
</dependency>
I am trying to implement a JUnit test to test an actor.
I have this ActorTest :
import org.junit.Test;
import play.libs.Akka;
import playtests.PlayFrameworkTest;
import akka.actor.Actor;
import akka.actor.Props;
import akka.actor.UntypedActorFactory;
import akka.testkit.TestActorRef;
public class ActorTest {
public static FakeApplication dummy;
#BeforeClass
public static void startApp() {
dummy = Helpers.fakeApplication(Helpers.inMemoryDatabase());
Helpers.start(dummy);
}
#AfterClass
public static void stopApp() {
Helpers.stop(dummy);
}
#Test
public void test() throws Exception {
final String myParameter = "someParameter";
#SuppressWarnings("serial")
TestActorRef<MyActor> actorRef = TestActorRef.create(Akka.system(), new Props(new UntypedActorFactory() {
#Override
public Actor create() {
return new MyActor(myParameter);
}
}), "testActor");
MyActor actor = actorRef.underlyingActor();
String message = "message";
actor.apply(message);
actor.receive();
}
}
When I try to run it (both on eclipse and with 'play test' commandline) is I get this exception thrown at the line of the TestActorRef.create()
java.lang.NoClassDefFoundError: scala/concurrent/duration/Duration
at persistence.actors.ActorTest.test(ActorTest.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassNotFoundException: scala.concurrent.duration.Duration
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 26 more
I have looked http://doc.akka.io/docs/akka/snapshot/java/testing.html
and
http://doc.akka.io/docs/akka/snapshot/scala/testing.html
and all I could find on the play framework page.
What am I missing? Why is it not running? I get the same exception if I get my system from Akka.system() and ActorSystem.apply() ... same thing when I pass it my fakeApplication or not.
(To summarise the comments above…) The class scala.concurrent.duration.Duration was first included with Scala 2.10. At the time of writing Akka 2.1 and Play 2.1 are the best releases to work with Scala 2.10.
I am testing a simple thing in my DB-Application. To create a product. For this I use Junit tests and here is the test that always fail, instead the expected result to turn green(passes)...
#Test
public void testCreate(){
Produkt test = new Produkt(20, "junit", "junitk", false, 900.67, true, true);
handler.createProdukt(test);
}
when I try it out simply with a main method(just creating a new Produkt and look if that works...) the create function works great and created this Produkt.
What am I doing wrong?
PS.: here is the code where I set up the tests:
#Before
public void setUp() throws SQLException, ClassNotFoundException{
try {
this.shandler = new ServiceHandler();
this.setServiceHandler(shandler);
manager.getConnection();
manager.getConnection().setAutoCommit(false);
} catch (SQLException ex) {
System.err.println("ERROR:");
ex.printStackTrace();
}
}
#After
public void tearDown() throws SQLException, ClassNotFoundException{
manager.getConnection().rollback();
manager.closeConnection();
}
UPDATE
I guess you mean the failure trace:
java.lang.NullPointerException at
tests.JUnitAbstractTests.testCreate(JUnitAbstractTests.java:35) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597) at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at
org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at
org.junit.runners.ParentRunner.run(ParentRunner.java:300) at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Assuming your code snippets are accurate, your setUp() method instantiates a shandler field while your testCreate() test uses a handler field. And the stacktrace clearly shows that you have a NullPointerException in testCreate(). So the thing that you are doing wrong is trying to call a method on an object whose value is null.
All Spring Configuration is written properly. Non-Multi-Exec Redis operations work perfectly.
#Autowired
#Qualifier("stringRedisTemplate")
StringRedisTemplate template;
void test(){
template.multi();
template.boundValueOps("somevkey").increment(1);
template.boundZSetOps("somezkey").add("zvalue", timestamp);
template.exec();
}
After running above code through Junit Test, Exceptions are thrown.
org.springframework.data.redis.RedisSystemException: Unknown exception; nested exception is org.springframework.data.redis.RedisSystemException: Unknown jedis exception; nested exception is java.lang.NullPointerException
at org.springframework.data.redis.connection.jedis.JedisUtils.convertJedisAccessException(JedisUtils.java:93)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.translateExceptionIfPossible(JedisConnectionFactory.java:155)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy66.appendUserStream(Unknown Source)
at com.uniu.test.repository.StreamCacheRepositoryTest.testAppendUserStream(StreamCacheRepositoryTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.data.redis.RedisSystemException: Unknown jedis exception; nested exception is java.lang.NullPointerException
at org.springframework.data.redis.connection.jedis.JedisConnection.convertJedisAccessException(JedisConnection.java:119)
at org.springframework.data.redis.connection.jedis.JedisConnection.exec(JedisConnection.java:523)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.data.redis.core.CloseSuppressingInvocationHandler.invoke(CloseSuppressingInvocationHandler.java:58)
at $Proxy70.exec(Unknown Source)
at org.springframework.data.redis.core.RedisTemplate$1.doInRedis(RedisTemplate.java:416)
at org.springframework.data.redis.core.RedisTemplate$1.doInRedis(RedisTemplate.java:412)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:162)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:133)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:121)
at org.springframework.data.redis.core.RedisTemplate.exec(RedisTemplate.java:412)
at com.uniu.repository.impl.StreamCacheRepositoryRedisImpl.appendUserStream(StreamCacheRepositoryRedisImpl.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
... 33 more
Caused by: java.lang.NullPointerException
at redis.clients.jedis.BinaryTransaction.exec(BinaryTransaction.java:31)
at org.springframework.data.redis.connection.jedis.JedisConnection.exec(JedisConnection.java:521)
... 54 more
I check redis server, the above two commands have been executed and the result is correct. So the problem comes at last line of the code (template.exec()). When underlying JedisClient try to get multibulk response from EXEC, it seems to throw NullPointerException
I use spring-data-redis 1.0.0.RELEASE
Thanks for help.
The reason for the exception is probably that the Spring template implementation does not reuse the same connection for .multi() and .exec(). You can try to use execute() via a callback:
private RedisTemplate template = ...;
template.execute(
new RedisCallback() {
#Override
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
connection.multi();
//do whatever you need, like deleting and repopulating some keys
connection.expire(CHANNEL_KEY.getBytes(), EXPIRE_SECS);
connection.exec();
return null;
}
}
);
template.setEnableTransactionSupport(true);
maybe you can use this to enable transaction
Piotr is right. You need to put it into SessionCallback.
Here is a quick summary of doing transactions with Spring Data Redis:
https://github.com/eric-wu/dashboard/wiki/3.-Redis-Transactions-via-Spring-Data-Redis
For your case, scroll down and look at "Optimistic locking using WATCH, MULTI, and EXEC".
Look at the implementatin of org.springframework.data.redis.support.collections.CollectionUtils.rename(K, K, RedisOperations<K, ?>)
and read about transaction details here
static <K> void rename(final K key, final K newKey, RedisOperations<K, ?> operations) {
operations.execute(new SessionCallback<Object>() {
#SuppressWarnings("unchecked")
public Object execute(RedisOperations operations) throws DataAccessException {
do {
operations.watch(key);
if (operations.hasKey(key)) {
operations.multi();
operations.rename(key, newKey);
} else {
operations.multi();
}
} while (operations.exec().isEmpty());
return null;
}
});
}
Note : While loop is important