I am trying to create native image from Quarkus Tika. I use below dependencies with this code snippet.
#Inject
TikaParser parser;
#POST
#Path("/text")
#Produces(MediaType.TEXT_PLAIN)
public String extractText(InputStream stream) {
Instant start = Instant.now();
String text = null;
try {
text = parser.getText(stream);
} catch (Exception e) {
log.info("error" + e);
}
<dependency>
<groupId>io.quarkiverse.tika</groupId>
<artifactId>quarkus-tika</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-awt</artifactId>
</dependency>
quarkus-quickstarts/tika-quickstart$ mvn clean install -Dnative
I used sample project from https://quarkiverse.github.io/quarkiverse-docs/quarkus-tika/dev/index.html
Even though i used "initialize-at-run-time" parameter for related classes, i got same error.
<quarkus.native.additional-build-args>--initialize-at-run-time=org.apache.sis.internal.system.DelayedExecutor\,org.apache.sis.internal.system.ReferenceQueueConsumer\,ucar.nc2.grib.grib2.Grib2JpegDecoder\,ucar.nc2.grib.grib2.Grib2DataReader2</quarkus.native.additional-build-args>
Here are my config files:
application.properties
quarkus.tika.tika-config-path=tika-config.xml
tika-config.xml
<?xml version="1.0" encoding="UTF-8"?> <properties> <parsers>
<parser class="org.apache.tika.parser.pdf.PDFParser">
<mime>application/pdf</mime>
</parser>
<parser class="org.apache.tika.parser.txt.TXTParser">
<mime>text/plain</mime>
</parser> </parsers> </properties>
Error:
Fatal error: org.graalvm.compiler.debug.GraalError: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Detected a started Thread in the image heap. Threads running in the image generator are no longer running at image runtime. To see how this object got instantiated use --trace-object-instantiation=org.apache.sis.internal.system.DelayedExecutor. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
at com.oracle.graal.pointsto.util.AnalysisFuture.setException(AnalysisFuture.java:49)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:269)
at com.oracle.graal.pointsto.util.AnalysisFuture.ensureDone(AnalysisFuture.java:63)
at com.oracle.graal.pointsto.heap.ImageHeapScanner.lambda$postTask$9(ImageHeapScanner.java:611)
at com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:193)
at com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:177)
at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Detected a started Thread in the image heap. Threads running in the image generator are no longer running at image runtime. To see how this object got instantiated use --trace-object-instantiation=org.apache.sis.internal.system.DelayedExecutor. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
at com.oracle.svm.hosted.image.DisallowedImageHeapObjectFeature.error(DisallowedImageHeapObjectFeature.java:173)
at com.oracle.svm.core.image.DisallowedImageHeapObjects.check(DisallowedImageHeapObjects.java:74)
at com.oracle.svm.hosted.image.DisallowedImageHeapObjectFeature.replacer(DisallowedImageHeapObjectFeature.java:149)
at com.oracle.graal.pointsto.meta.AnalysisUniverse.replaceObject(AnalysisUniverse.java:582)
at com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider.replaceObject(AnalysisConstantReflectionProvider.java:257)
at com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider.interceptValue(AnalysisConstantReflectionProvider.java:228)
at com.oracle.svm.hosted.heap.SVMImageHeapScanner.transformFieldValue(SVMImageHeapScanner.java:126)
at com.oracle.graal.pointsto.heap.ImageHeapScanner.onFieldValueReachable(ImageHeapScanner.java:331)
at com.oracle.graal.pointsto.heap.ImageHeapScanner.lambda$createImageHeapObject$3(ImageHeapScanner.java:272)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
... 10 more
Related
I am using ProceedingJoinPoint in my springboot application to capture arguments passed to log.info. I am using aspectjweaver-1.9.7. I have added the following dependencies in my maven pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
I have created a library which is basically a wrapper around slf4j logger. So whenever log.info or log.debug is called, I have written an #Aspect class called LoggerAspect , in which I have a #Around Method which will do the required work.
Here is the #Around Method
#Around("call(* org.slf4j.Logger.info(..))")
public void injectLogConfigInfo(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(pjp.getArgs().length);
Object[] args = logMod(pjp.getArgs());
pjp.proceed(args);
MDC.clear();
}
Now, when i am implementing the logger in my application , i am facing the following issue:
Example: log.info("This is test of info", SomeObject);
when i am passing this, pjp is only picking up the first String but it is ignoring the object. I had read that it returns all the arguments as an object[] array. The method logmod(pjp.getArgs()) does some processing on the object array which pjp returns. I am not that proficient in posting questions so do forgive me for missing out on details.
Due to restrictions at my org, i cannot post the whole code but i have included the required bits. Now I know that when debugging, it is beneficial to view the whole picture but I do not have that priviledge. So even if you do not have the exact answer, if you can share your experience whether you have faced this issue and what you did to resolve it?
Thanks
I am facing a issue with the circuit breaker implementation using Spring Cloud Resilience4j.
Following some tutorial, I have tried to add the necessary dependencies in the project.
Also, tried to add the configurations but, still the circuit is not opening and fallback method is not getting called.
For the use case, I am calling an external API from my service and if that external API is down then after few calls I need to enable the circuit breaker.
Please find the code pieces from the different files.
I am a newbie to circuit breaker pattern. Any help will be highly appreciated.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2020.0.4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependencies>
</project>
Application properties
resilience4j.circuitbreaker.instances.test-api.register-health-indicator=true
resilience4j.circuitbreaker.instances.test-api.minimum-number-of-calls=4
resilience4j.circuitbreaker.instances.test-api.failure-rate-threshold=50
resilience4j.circuitbreaker.instances.test-api.permitted-number-of-calls-in-half-open-state=3
resilience4j.circuitbreaker.instances.test-api.wait-duration-in-open-state=30s
resilience4j.circuitbreaker.instances.test-api.automatic-transition-from-open-to-half-open-enabled=true
resilience4j.circuitbreaker.instances.test-api.record-exceptions=com.testapi.exception.ServiceUnavailableError
Service Class Code Piece
#CircuitBreaker(name = "test-api", fallbackMethod = "storeResponseFallback")
public TestResponse storeResponse(String apiURL, HttpEntity<String> entityrequest) {
TestResponse testResponse = new TestResponse();
Optional<ResponseEntity<TestResponse>> response = Optional.empty();
Future<ResponseEntity<TestResponse>> responseFuture;
ExecutorService executor = Executors.newFixedThreadPool(10);
log.debug("Calling Extrenal API, Request Body: {}", entityrequest.toString());
try {
//Service call returns a future
responseFuture = executor.submit(() -> restTemplate.postForEntity(apiURL, entityrequest, TestResponse.class));
response = Optional.ofNullable(responseFuture.get());
log.info("Got response from external API");
if ((response.isPresent()) && (response.get().hasBody())) {
testResponse = response.get().getBody();
}
} catch (Exception exception) {
log.error("External api call got failed with an error");
Thread.currentThread().interrupt();
throw new ServiceUnavailableError();
}
return testResponse;
}
public TestResponse storeResponseFallback(ServiceUnavailableError ex) {
log.error("Executing Fallback Method For General exceptions");
throw new ServiceUnavailableError();
}
ServiceUnavailableError Java file
#Data
#AllArgsConstructor
#NoArgsConstructor
public class ServiceUnavailableError extends RuntimeException{
private static final long serialVersionUID = 2382122402994502766L;
private String message;
}
The signature of your fallback method is wrong. It should contain all the parameters of the actual method ( in your case storeResponseFallback is the fallback method and storeResponse is the actual method), along with the exception. Please make sure to remove the try catch block. You do not want to handle the exception yourself, rather you should let circuit breaker to handle it for you.
Please take a look at the following code which is from given link
https://resilience4j.readme.io/docs/getting-started-3
#CircuitBreaker(name = BACKEND, fallbackMethod = "fallback")
public Mono<String> method(String param1) {
return Mono.error(new NumberFormatException());
}
private Mono<String> fallback(String param1, IllegalArgumentException e) {
return Mono.just("test");
}
Try using the following yaml file
I used the following configuration with your existing code,I used yaml instead of properties file. this seems to stay in open state and call only the fallback method.
resilience4j.circuitbreaker:
configs:
default:
slidingWindowSize: 4
permittedNumberOfCallsInHalfOpenState: 10
waitDurationInOpenState: 10000
failureRateThreshold: 60
eventConsumerBufferSize: 10
registerHealthIndicator: true
someShared:
slidingWindowSize: 3
permittedNumberOfCallsInHalfOpenState: 10
instances:
test-api:
baseConfig: default
waitDurationInOpenState: 500000
backendB:
baseConfig: someShared
Here is the updated fallback method
public TestResponse storeResponseFallback(String apiURL, String entityrequest, java.lang.Throwable t) {
log.error("Executing Fallback Method For General exceptions "+t.getMessage());
return new TestResponse("Frm Fallback");// Making sure to send a blank response
}
I have prepared the video, where I have defined main service and target service and I am preparing the bean from config and making use of Try.of() please check the video if it help.
you will see that the fallback method is working fine.
https://www.youtube.com/watch?v=8yJ0xek6l6Y&t=31s
I'm new to Spring Integration and am trying to develop an application which simply (1) polls a folder for new files with extension .dat containing data in csv format (2) initialize for each line a domain POJO object of class RecordDTO and finally (3) sends this object as payload to a REST service with a POST.
For this I'm trying to use Java DSL for Spring Integration.
The problem I'm getting is the following VerifyError / HttpRequestExecutingMessageHandler overrides final method onInit. exception.
2016-07-22 10:01:38.965 ERROR 4460 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'upcase' defined in eu.softeco.examples.SpringBootIntegrationTestApplication: Initialization of bean failed; nest
ed exception is java.lang.VerifyError: class org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler overrides final method onInit.()V
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.1.RELEASE.jar:4.3.1.RELEASE]
...
Caused by: java.lang.VerifyError: class org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler overrides final method onInit.()V
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_45]
at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_45]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_45]
...
Below are relevant details concerning my code and maven configuration. Please not that
1) the problem is at startup, before any data is put in the input folder
2) if I replace the final Http outboundGateway step with the simple (commented) System.out.println, everything works fine.
Following are code/config details. This is my main Spring Boot application class with Spring Integration Flow definition:
#SpringBootApplication
#EnableIntegration
#IntegrationComponentScan
public class SpringBootIntegrationTestApplication {
...
public static void main(String[] args) {
SpringApplication.run(SpringBootIntegrationTestApplication.class, args);
}
/**
* Inbound FileReadingMessageSource
*/
#Bean
#InboundChannelAdapter(channel = "upcase.input", poller = #Poller(fixedDelay = "4000"))
public MessageSource<File> fileReadingMessageSource() {
FileReadingMessageSource source = new FileReadingMessageSource();
source.setDirectory(new File(INBOUND_PATH));
source.setFilter(new SimplePatternFileListFilter("*.dat"));
return source;
}
/**
* Spring Integration Java DSL Flow
*/
#Bean
public IntegrationFlow upcase() {
FileToStringTransformer fileToStringTranformer = Transformers.fileToString();
fileToStringTranformer.setDeleteFiles(true);
return flow -> flow
// get string contents from fie
.transform(fileToStringTranformer)
// split into individual lines
.split( s -> s.applySequence(true).get().getT2().setDelimiters("\n"))
// cleanup lines from trailing returns
.transform( (String s) -> s.replace("\n", "").replace("\r", "") )
// convert csv string to RecordDTO object
.transform("#recordFromCsvTransformer.transform(payload)")
// print on System.out
// .handle(m -> System.out.println(m.getPayload()))
// send to
.handle(Http.outboundGateway("http://localhost:8080/records")
.httpMethod(HttpMethod.POST)
.expectedResponseType(RecordDTO.class));
}
}
Below the RecordFromCsvTransformer class
#Component
public class RecordFromCsvTransformer
{
#Transformer
public RecordDTO transform(String csvline) throws Exception {
RecordDTO record = new RecordDTO();
... parse csv and initialize record's fields...
return record;
}
}
And Finally the relevant parts of pom.xml (dependencies);
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RC1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-http</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
...
</dependencies>
...
As a side question in general, can someone suggest me some good tutorial / getting started guide to learn Spring Integration with Java Annotation/Java DSL? So far I've only found either introductory guide based on Spring Integration XML configuration or material about Java Annotations/DSL but that already requires prior knowledge of Spring Integration.
<version>2.1.0.RELEASE</version>
That version of Spring Integration is mismatched with the spring-integration-core version brought in transitively by maven.
You need to use the same version of all spring-integration-* files - check which version of spring-integration-file is being pulled in by boot and use the same version.
I am trying to insert an array to postgres using java code , but I always get this error :
SEVERE [http-nio-8080-exec-2]org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service()
for servlet [] in context with path [/] threw exception
[Servlet execution threw an exception] with root cause
java.lang.AbstractMethodError:
com.mchange.v2.c3p0.impl.NewProxyConnection.createArrayOf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/sql/Array;
Code Used
pst = getConnection().prepareStatement(INSERT_QUERY,PreparedStatement.RETURN_GENERATED_KEYS);
pst.setString(1, t.getname());
pst.setString(2, t.getEmail());
Array itemIds = conn.createArrayOf("bigint", t.getItemIds());
pst.setArray(3, itemIds);
If I run the function through main class it works fine , but after deploying to tomcat server, http calls fail with above error .
DB Used - Postgres
JDBC Driver postgres-9.1-901-1.jdbc4
c3p0-0.9.5-pre10
tomcat-8.0.24
As per research I have done , createArrayOf() supposed to work with jdbc4 and c3p0-0.9.5 .
Using this works fine , but I don't see it as right approach
if (conn instanceof C3P0ProxyConnection) {
C3P0ProxyConnection proxy = (C3P0ProxyConnection) conn;
try {
Method m = Connection.class.getMethod("createArrayOf", String.class, Object[].class);
Object[] args = { "bigint", t.getItemIds() };
itemIds = (Array) proxy.rawConnectionOperation(m, C3P0ProxyConnection.RAW_CONNECTION, args);
} catch (IllegalArgumentException e) {
throw new SQLException(e);
}
} else {
itemIds = conn.createArrayOf("bigint", t.getItemIds());
}
Need help .
Thanks
I strongly suspect that you have an older version of c3p0 somewhere in your application's effective CLASSPATH. I've downloaded and verified from c3p0-0.9.5-pre10.jar and c3p0-0.9.5.1.jar on Maven Central that com.mchange.v2.c3p0.impl.NewProxyConnection does in fact contain the createArrayOf method.
% javap -sysinfo -cp ./c3p0-0.9.5.1.jar com.mchange.v2.c3p0.impl.NewProxyConnection
Classfile jar:file:/Users/swaldman/tmp/c3p0jars/c3p0-0.9.5.1.jar!/com/mchange/v2/c3p0/impl/NewProxyConnection.class
Last modified Jun 16, 2015; size 27098 bytes
MD5 checksum c1ff36b87219ddc84c92fb6c1445a2d1
Compiled from "NewProxyConnection.java"
public final class com.mchange.v2.c3p0.impl.NewProxyConnection implements java.sql.Connection,com.mchange.v2.c3p0.C3P0ProxyConnection {
//...
public synchronized java.sql.Array createArrayOf(java.lang.String, java.lang.Object[]) throws java.sql.SQLException;
//...
}
Although this is not likely the cause of your problem, I recommend that you do upgrade to c3p0-0.9.5.1 rather than using the prerelease version.
To see what version of c3p0 your application is actually using, look at INFO in your log files for the banner printed when the c3p0 library is initialized. It should look something like this:
INFO: Initializing c3p0-0.9.5.1 [built 16-June-2015 00:06:36 -0700; debug? true; trace: 10]
I suspect that you will see an older version, that somewhere, perhaps among the transitive dependencies, you are pulling in 0.9.1.x or 0.9.2.x versions of the library.
Good luck!
I can see you are using old version of the c3p0 library.
if you are using maven, update the library to higher version in you pom file from
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
to
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
I hope it help someone.
Updating dependency to following solved my problem.
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
I'm trying to run simple Spring Data Rest Boot app (v1.2.3.RELEASE) with only one small modification from working Spring reference example app (http://spring.io/guides/gs/accessing-mongodb-data-rest/) and it failed to start.
To be more specific when I use:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
and just following simple code configuration:
public class Application {
public static void main(String[] args){
SpringApplication.run(Config.class, args);
}
}
#SpringBootApplication
public class Config {
}
without anything else I'm getting following error on startup:
2015-04-20 12:07:32.250 ERROR 5693 --- [ main]
o.s.boot.SpringApplication : Application startup failed
org.springframework.context.ApplicationContextException: Unable to
start embedded container; nested exception is
org.springframework.boot.context.embedded.EmbeddedServletContainerException:
Unable to start embedded Tomcat ...
Caused by:
java.lang.ClassCastException:
jug.ua.json.test.Config$$EnhancerBySpringCGLIB$$79797226 cannot be
cast to
org.springframework.data.rest.core.config.RepositoryRestConfiguration
at
org.springframework.boot.autoconfigure.data.rest.SpringBootRepositoryRestMvcConfiguration$$EnhancerBySpringCGLIB$$3a999d99.config()
...
However following code configuration is working fine:
#SpringBootApplication
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
Also if instead I use:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
separate Java config class approach is working fine as well...
What I'm doing wrong, cause I can't believe I spotted such an obvious bug?
Thank you,
Oleg
The problem appears to be due to a name clash between the config bean method on SpringBootRepositoryRestMvcConfiguration (inherited from Spring Data REST's RepositoryRestMvcConfiguration) and your configuration class named Config. Renaming it to something other than Config should get things working again.