Apache Camel 3.4 - Various Unmarshalling Errors Using Jackson - jackson

I have succesfully written a simple use-case to unmarshal a JSON response from the Quickbooks oAuth API to refresh tokens.
With that working, I need to go and fetch the actual data:
https://quickbooks.api.intuit.com/v3/company/XXXXXXXXXXXXXX/query?query=SELECT * FROM Invoice WHERE Metadata.LastUpdatedTime%3E='2020-07-01T01:00:00' ORDERBY Metadata.LastUpdatedTime, Id STARTPOSITION 1 MAXRESULTS 1000 &minorversion=47
The HTTP call works OK:
// make the HTTP REST call, without C10y* & Camel* headers:
.toD("https://${header." + Headers.IEP_API_HOST + "}?headerFilterStrategy=C10yHeaderFilterStrategy")
I can check that the JSON returned is OK:
.log(LoggingLevel.DEBUG, API_LOG, "JSON returned: ${body}")
But from here it goes pear-shaped:
.unmarshal().json(JsonLibrary.Jackson, Payload.class)
This is what happens:
With the above log statement a MismatchedInputException is raised with the message "No content to map due to end-of-input".
Without the above log statement a ClassNotFoundException is raised with the message "Payload.class".
Re. 1.
My understanding is that responses are cached by default so it should be possible to read the inputstream multiple times. By default the HTTP endpoint option disableStreamCache is set to false, so it's enabled.
The stack trace is:
com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
at [Source: (org.apache.camel.converter.stream.CachedOutputStream$WrappedInputStream); line: 1, column: 0]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[jackson-databind-2.11.0.jar:2.11.0]
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4624) ~[jackson-databind-2.11.0.jar:2.11.0]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4469) ~[jackson-databind-2.11.0.jar:2.11.0]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3471) ~[jackson-databind-2.11.0.jar:2.11.0]
at org.apache.camel.component.jackson.JacksonDataFormat.unmarshal(JacksonDataFormat.java:188) ~[camel-jackson-3.4.0.jar:3.4.0]
at org.apache.camel.support.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:64) ~[camel-support-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.doRun(RedeliveryErrorHandler.java:702) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.run(RedeliveryErrorHandler.java:616) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:60) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:147) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:286) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:203) ~[camel-timer-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:76) ~[camel-timer-3.4.0.jar:3.4.0]
at java.base/java.util.TimerThread.mainLoop(Timer.java:556) ~[na:na]
at java.base/java.util.TimerThread.run(Timer.java:506) ~[na:na]
Re. 2.
The stack trace for this is:
org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-WIN-10-DM-1594724136485-0-1]
at org.apache.camel.CamelExecutionException.wrapCamelExecutionException(CamelExecutionException.java:47) ~[camel-api-3.4.0.jar:3.4.0]
at org.apache.camel.language.simple.SimpleExpressionBuilder$26.evaluate(SimpleExpressionBuilder.java:590) ~[camel-core-languages-3.4.0.jar:3.4.0]
at org.apache.camel.support.ExpressionAdapter.evaluate(ExpressionAdapter.java:36) ~[camel-support-3.4.0.jar:3.4.0]
at org.apache.camel.reifier.language.SimpleExpressionReifier$1.evaluate(SimpleExpressionReifier.java:42) ~[camel-core-engine-3.4.0.jar:3.4.0]
at org.apache.camel.processor.SetHeaderProcessor.process(SetHeaderProcessor.java:48) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.doRun(RedeliveryErrorHandler.java:702) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryTask.run(RedeliveryErrorHandler.java:616) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:60) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:147) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:286) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:203) ~[camel-timer-3.4.0.jar:3.4.0]
at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:76) ~[camel-timer-3.4.0.jar:3.4.0]
at java.base/java.util.TimerThread.mainLoop(Timer.java:556) ~[na:na]
at java.base/java.util.TimerThread.run(Timer.java:506) ~[na:na]
Caused by: java.lang.ClassNotFoundException: Payload.class
at org.apache.camel.impl.engine.DefaultClassResolver.resolveMandatoryClass(DefaultClassResolver.java:87) ~[camel-base-3.4.0.jar:3.4.0]
at org.apache.camel.language.simple.SimpleExpressionBuilder$26.evaluate(SimpleExpressionBuilder.java:588) ~[camel-core-languages-3.4.0.jar:3.4.0]
... 13 common frames omitted
All of this is running within an Eclipse/Maven project, so I have cleaned, refreshed, compiled, rebuilt, etc, etc, to no avail.
I have written a simple jUnit and it works absolutely fine using the JSON from the above log, saved to a file:
/**
* POJO Jackson unmarshalling
*/
#Test
public void pojoUnmarshallTest() {
ObjectMapper om = new ObjectMapper();
try {
Payload payload = om.readValue(getFile("qb.Payload.Invoice.json"), Payload.class);
assertTrue(payload.toString().startsWith("c10y.model.qb.Payload"));
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
Lastly, I'm using the latest versions of Camel & Spring Boot:
<properties>
<!-- latest versions # Jul 2020 -->
<java.version>11</java.version>
<camel.version>3.4.0</camel.version> <!-- latest long term support version -->
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<run.profiles>dev</run.profiles>
</properties>
As ever, thanks in advance for your help!
PS:
The POJO classes that receive the unmarshalled JSON were generated at http://www.jsonschema2pojo.org/. The POJO for the working route was hand-cranked. I mention it just in case it could make a difference (it shouldn't IMHO).
The entire route can be obtained here: https://drive.google.com/file/d/1Qu0vwJaSlggH6BrIgUFMU_BZNpmMQYuh/view?usp=sharing.
I have tried the Gson library and get the same ClassNotFoundException: Payload.class error. This is looking like less of an unmarshalling problem and more of a classpath issue.
Having two .log() statements gives the following output:
2020-07-15 10:06:27.108 DEBUG 6720 --- [mer://startHere] c.c.r.qb.fetch.delta : JSON returned: {"QueryResponse":{"Invoice":[{"AllowIPNPayment":false, ...removed... ,"Balance":0}],"startPosition":1,"maxResults":1,"totalCount":1},"time":"2020-07-15T02:06:21.869-07:00"}
2020-07-15 10:06:27.108 DEBUG 6720 --- [mer://startHere] c.c.r.qb.fetch.delta : JSON returned:
Contrary to the documentation, it looks like the input stream is not, in fact, cached.
PS2:
Adding .streamCaching() to the route and &disableStreamCache=false to the endpoint URI didn't make any difference to the second .log(); it remained empty.
I also tried the following Java Config approach:
#Configuration
public class Config {
#Bean
CamelContextConfiguration contextConfiguration() {
return new CamelContextConfiguration() {
#Override
public void beforeApplicationStart(CamelContext context) {
System.out.println("****** beforeApplicationStart ******");
}
#Override
public void afterApplicationStart(CamelContext context) {
System.out.println("****** afterApplicationStart ******");
context.setStreamCaching(true);
}
};
}
}
I can see the sysout in the console but this didn't work either.
I downloaded jsonschema2pojo-1.0.2 and ran it against a much bigger JSON sample with the following arguments:
--annotation-style JACKSON2
--big-decimals
--date-class java.util.Date
--format-dates
--format-date-times
--package c10y.model.qb.jxon
--remove-old-output
--source C:\Users\...\src\test\resources\qb.Payload.Invoice.json
--source-type JSON
--target c:\temp
--target-language JAVA
--target-version 11
This created the root/base POJO called QbPayloadInvoice, which looks like it's taken from the input file name. I updated my route:
.unmarshal().json(JsonLibrary.Jackson, QbPayloadInvoice.class)
It still raises the java.lang.ClassNotFoundException: Payload.class.
There's nothing in the JSON response, or in any of the other generated POJOs, called Payload.
At the same time, my updated jUnit works fine:
QbPayloadInvoice payload = om.readValue(getFile("qb.Payload.Invoice.json"), QbPayloadInvoice.class);
expected = "c10y.model.qb.jxon.QbPayloadInvoice";
assertEquals(expected, payload.toString().substring(0, expected.length()));
Go figure!

The clue exists above where I wrote "There's nothing in the JSON response, or in any of the other generated POJOs, called Payload." This statement turned out to be absolutely correct.
The unmarshalling had been working all along:
.unmarshal().json(JsonLibrary.Jackson, QbPayloadInvoice.class)
It was the following line that was failing:
.setHeader(QB_START_POS, simple("${bodyAs(Payload.class).QueryResponse.startPosition}"))
This was made more obvious given that I'd changed the unmarshalling class from Payload to QbPayloadInvoice.

Related

Problems with a get request via RestClient in Groovy

I'm new to Groovy and a bit rusty on development.
I am trying to make a GET request to a woocommerce API. With Postman it works OK but not in Groovy it is not entirely clear to me what you need to cast from String to Map Entry.
I imagine it's something relatively simple but I can't find it.
Thanks a lot.
#Grab('com.github.groovy-wslite:groovy-wslite:1.1.2')
import groovy.json.JsonSlurper
import wslite.rest.*
def request
RESTClient client = new RESTClient("https://www.somewoomcersite.com")
def path = "/wp-json/wc/v3/customers"
request = client.get(path: path, headers: ["Authorization", "BLA BLA"])
Caught: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map$Entry
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map$Entry
at wslite.rest.RESTClient.createRequestParams(RESTClient.groovy:118)
at wslite.rest.RESTClient.this$2$createRequestParams(RESTClient.groovy)
at wslite.rest.RESTClient.executeMethod(RESTClient.groovy:93)
at wslite.rest.RESTClient.this$2$executeMethod(RESTClient.groovy)
at wslite.rest.RESTClient.get(RESTClient.groovy:49)
at wslite.rest.RESTClient.get(RESTClient.groovy)
at wslite.rest.RESTClient$get.call(Unknown Source)
at MAG.run(MAG.groovy:9)
An example json of the response would be this:
https://woocommerce.github.io/woocommerce-rest-api-docs/#list-all-customers

io.helidon.webserver.ServerResponse.send() throwing error on server but file downloaded on front end

Trying to write one sample for (file upload and download) error in server.
Though it downloads the file in the frontend, getting error in server.
For Routing--
WebServer.builder(getRouting()).port(8080).build().start();
private static Routing getRouting() throws Exception{
return Routing.builder().register("/filetest", JerseySupport.builder().register(FileController.class).build())
.build();
}
#RequestScoped
public class FileController {
#Context
ServerRequest req;
#Context
ServerResponse res;
#GET
#Path("/{fname}")
public void download(#PathParam("fname") String fname) {
try {
//Getting the file
java.nio.file.Path filepath = Paths.get("c:/"+fname+".txt");
ResponseHeaders headers = res.headers();
headers.contentType(io.helidon.common.http.MediaType.APPLICATION_OCTET_STREAM);
headers.put(Http.Header.CONTENT_DISPOSITION, ContentDisposition.builder()
.filename(filepath.getFileName().toString())
.build()
.toString());
res.send(filepath);
}catch(Exception e) {
}
}
Jul 29, 2021 6:20:36 PM
io.helidon.webserver.RequestRouting$RoutedRequest defaultHandler
WARNING: Default error handler: Unhandled exception encountered.
java.util.concurrent.ExecutionException: Unhandled 'cause' of this
exception encountered. at
io.helidon.webserver.RequestRouting$RoutedRequest.defaultHandler(RequestRouting.java:397)
at
io.helidon.webserver.RequestRouting$RoutedRequest.nextNoCheck(RequestRouting.java:377)
at
io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:420)
at
io.helidon.webserver.jersey.ResponseWriter.failure(ResponseWriter.java:133)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:438)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) at
org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) at
org.glassfish.jersey.internal.Errors.process(Errors.java:292) at
org.glassfish.jersey.internal.Errors.process(Errors.java:274) at
org.glassfish.jersey.internal.Errors.process(Errors.java:244) at
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
at
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234)
at
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
at
io.helidon.webserver.jersey.JerseySupport$JerseyHandler.lambda$doAccept$3(JerseySupport.java:299)
at io.helidon.common.context.Contexts.runInContext(Contexts.java:117)
at
io.helidon.common.context.ContextAwareExecutorImpl.lambda$wrap$5(ContextAwareExecutorImpl.java:154)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834) Caused by:
io.helidon.common.http.AlreadyCompletedException: Response status code
and headers are already completed (sent to the client)! at
io.helidon.webserver.HashResponseHeaders$CompletionSupport.runIfNotCompleted(HashResponseHeaders.java:384)
at
io.helidon.webserver.HashResponseHeaders.httpStatus(HashResponseHeaders.java:251)
at io.helidon.webserver.Response.status(Response.java:122) at
io.helidon.webserver.Response.status(Response.java:48) at
io.helidon.webserver.jersey.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:81)
at
org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:607)
at
org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:373)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:363)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:258)
... 14 more
Jul 29, 2021 6:20:36 PM
io.helidon.webserver.RequestRouting$RoutedRequest defaultHandler
WARNING: Cannot perform error handling of the throwable (see cause of
this exception) because headers were already sent
java.lang.IllegalStateException: Headers already sent. Cannot handle
the cause of this exception. at
io.helidon.webserver.RequestRouting$RoutedRequest.defaultHandler(RequestRouting.java:405)
at
io.helidon.webserver.RequestRouting$RoutedRequest.nextNoCheck(RequestRouting.java:377)
at
io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:420)
at
io.helidon.webserver.jersey.ResponseWriter.failure(ResponseWriter.java:133)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:438)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) at
org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) at
org.glassfish.jersey.internal.Errors.process(Errors.java:292) at
org.glassfish.jersey.internal.Errors.process(Errors.java:274) at
org.glassfish.jersey.internal.Errors.process(Errors.java:244) at
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
at
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234)
at
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
at
io.helidon.webserver.jersey.JerseySupport$JerseyHandler.lambda$doAccept$3(JerseySupport.java:299)
at io.helidon.common.context.Contexts.runInContext(Contexts.java:117)
at
io.helidon.common.context.ContextAwareExecutorImpl.lambda$wrap$5(ContextAwareExecutorImpl.java:154)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834) Caused by:
io.helidon.common.http.AlreadyCompletedException: Response status code
and headers are already completed (sent to the client)! at
io.helidon.webserver.HashResponseHeaders$CompletionSupport.runIfNotCompleted(HashResponseHeaders.java:384)
at
io.helidon.webserver.HashResponseHeaders.httpStatus(HashResponseHeaders.java:251)
at io.helidon.webserver.Response.status(Response.java:122) at
io.helidon.webserver.Response.status(Response.java:48) at
io.helidon.webserver.jersey.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:81)
at
org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:607)
at
org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:373)
at
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:363)
at
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:258)
... 14 more
When using Helidon MP, Jersey is responsible for sending the response.
In the code above you are using the underlying WebServer and sending a response inside the body of a JAXRS resource method, when Jersey sends the response the exception is thrown because it was already sent.
Helidon MP Multipart example
Jersey Multipart documentation

Swagger definition errors

Trying to use Swagger on my JAX-RS application with enunciate Maven plugin.
The generated JSON definition works well.
But when I try to validate it online with Swagger Editor, the converted YAML file has some weird errors.
For example:
Definition:
parameters:
- name: body
in: body
type: file
description: 'Bla bla'
responses:
'201':
ERROR:
Parameters with "type: file" must have "in: formData"
JAX-RS Code:
#POST
#Path(value = "/validatedata")
public Response validate(ValidateDataFromInput validateDataFromInput) throws CustomException {
return Response.status(Status.ACCEPTED).entity(validationActionService.getDataFromInput(validateDataFromInput.getConsumerInput(),
validateDataFromInput.getValidateInput(), null)).build();
}
I am using: swagger-core-1.5.21 and enunciate-maven-plugin-2.11.1.
Not sure which is wrong here.

Symfony - No Extension Is Able To Load The Configuration (Subscriber/Event Listening) (REST API Exception Handling with JSON output)

Purpose
Hello, I am fairly new to Symfony and am trying to create an exception/error handling functionality for our Web API.
Requirements
When a user makes an invalid request to our API, we want to return a simple JSON object that looks something like the following:
{"errorCode": 1234567, "errorMessage": "Parameter 1 is invalid. String expected"}
In addition to API-specific errors, we also want to hook into the built-in exception-handling in Symfony and re-use that, but instead of returning an HTML error page (which is what happens by default), we want to return a JSON object like:
{"errorCode": 404, "errorMessage": "Not found"}
Current Approach
Obviously, we want this to be implemented in the most efficient way, so after doing some research, I found what I think is a great approach which I can then adapt to our specific needs. Here is the tutorial I followed:
https://knpuniversity.com/screencast/symfony-rest2
I ended up buying this course in order to get access to the full code. The issue is that it was written for Symfony 2, but we are running Symfony 3.3, so some things are outdated and I have not been able to get the example running yet.
Code
So, I have posted some of the relevant code below. (I obviously cannot post the whole code, but have posted what are hopefully the relevant portions of the publicly-available code).
services.yml (Their version, Symfony 2 Style)
api_exception_subscriber:
class: AppBundle\EventListener\ApiExceptionSubscriber
arguments: []
tags:
- { name: kernel.event_subscriber }
services.yml (my full file with all comments removed)
This includes a modified version of what they have above (hopefully this is the correct Symfony 3.3 way of doing things).
NOTE: Anything that was part of the private code which I cannot show, I have replaced with the word "something".
parameters:
services:
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
AppBundle\EventListener\ApiExceptionSubscriber:
arguments:
- ['%something.something%']
tags:
- {name: 'kernel.event_subscriber'}
routing.yml (relevant section of their file)
app_api:
resource: "#AppBundle/Controller/Api"
type: annotation
defaults:
_format: json
routing.yml (my full file) - NOTE: I had to add the "_format: json" directly to the "app" section here rather than "app_api" because in our REST API, all of our URLs are at the root level, and do NOT have to be prefixed with "api" like http://localhost/api/someMethod/someMethodParameter as in the tutorial's code
app:
resource: '#AppBundle/Controller/'
type: annotation
defaults: {_format:json}
yml_route:
path: /yml-route
defaults:
_controller: AppBundle:Default:yml
awesome_route:
path: /awesome-route/{ic}
defaults:
_controller: AppBundle:Rest:awesomeRoute
src/AppBundle/RestController.php (edited to show just the basic structure)
<?php
namespace AppBundle\Controller;
use FOS\RestBundle\Controller\Annotations as Rest;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\HttpFoundation\Request;
class RestController extends Controller {
public function doSomething($id)
{
// Code to populate $result with data from database is here
return new JsonResponse($result);
}
// This file contains many different functions similar to doSomething() which retrieve the request for the API caller.
// For example, doSomething() can be accessed via http://localhost/app_dev.php/doSomething/123
}
src/AppBundle/Api/ApiProblem.php (edited to show just the basic structure)
namespace AppBundle\Api;
use Symfony\Component\HttpFoundation\Response;
class ApiProblem
{
// Code relevant to this class is in here
}
src/AppBundle/Api/ApiProblemException.php (edited to show just the basic structure)
<?php
namespace AppBundle\Api;
use Symfony\Component\HttpKernel\Exception\HttpException;
class ApiProblemException extends HttpException
{
private $apiProblem;
public function __construct($severalParametersWhichICannotListHereBecauseCodeIsPrivate) {
// Does some stuff and then calls the parent:__construct
// Includes a getter for $apiProblem
}
}
src/AppBundle/EventListener/ApiExceptionSubscriber.php (edited to show just the basic structure)
<?php
namespace AppBundle\EventListener;
use AppBundle\Api\ApiProblem;
use AppBundle\Api\ApiProblemException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\KernelEvents;
class ApiExceptionSubscriber implements EventSubscriberInterface
{
// Code relevant to this subscriber is here
}
The Issue
I'm getting the following error when I try to run any type of command from the command-line bin/console:
C:\htdocs\projects\myproject>php bin/console debug:container
PHP Fatal error: Uncaught Symfony\Component\DependencyInjection\Exception\InvalidArgumentException: T
here is no extension able to load the configuration for "AppBundle\EventListener\ApiExceptionSubscribe
r" (in C:\htdocs\projects\myproject\app/config\services.yml). Looked for namespace "AppBundle\EventListe
ner\ApiExceptionSubscriber", found "framework", "security", "twig", "monolog", "swiftmailer", "doctrin
e", "sensio_framework_extra", "demontpx_parsedown", "doctrine_cache", "doctrine_migrations", "debug",
"web_profiler", "sensio_distribution", "web_server" in C:\htdocs\projects\myproject\vendor\symfony\symfo
ny\src\Symfony\Component\DependencyInjection\Loader\YamlFileLoader.php:644
Stack trace:
#0 C:\htdocs\projects\myproject\vendor\symfony\symfony\src\Symfony\Component\DependencyInjection\Loader\
YamlFileLoader.php(614): Symfony\Component\DependencyInjection\Loader\YamlFileLoader->validate(Array,
'C:\\htdocs\\proje...')
#1 C:\htdocs\projects\myproject\vendor\symfony\symfony\src\Symfony\Component\DependencyInjection\Loader\
YamlFileLoad in C:\htdocs\projects\myproject\vendor\symfony\symfony\src\Symfony\Component\Config\Loader\
FileLoader.php on line 179
Fatal error: Uncaught Symfony\Component\DependencyInjection\Exception\InvalidArgumentException: There
is no extension able to load the configuration for "AppBundle\EventListener\ApiExceptionSubscriber" (i
n C:\htdocs\projects\myproject\app/config\services.yml). Looked for namespace "AppBundle\EventListener\A
piExceptionSubscriber", found "framework", "security", "twig", "monolog", "swiftmailer", "doctrine", "
sensio_framework_extra", "demontpx_parsedown", "doctrine_cache", "doctrine_migrations", "debug", "web_
profiler", "sensio_distribution", "web_server" in C:\htdocs\projects\myproject\vendor\symfony\symfony\sr
c\Symfony\Component\Config\Loader\FileLoader.php on line 179
Symfony\Component\Config\Exception\FileLoaderLoadException: There is no extension able to load the con
figuration for "AppBundle\EventListener\ApiExceptionSubscriber" (in C:\htdoc
fig\services.yml). Looked for namespace "AppBundle\EventListener\ApiExceptio
work", "security", "twig", "monolog", "swiftmailer", "doctrine", "sensio_fra
arsedown", "doctrine_cache", "doctrine_migrations", "debug", "web_profiler",
eb_server" in C:\htdocs\projects\myproject\app/config\services.yml (which is b
ocs\projects\myproject\app/config\config.yml"). in C:\htdocs\projects\myproject\
\Symfony\Component\Config\Loader\FileLoader.php on line 179
Call Stack:
1.4353 6149416 1. Symfony\Component\Debug\ErrorHandler->handleExcep
myproject\vendor\symfony\symfony\src\Symfony\Component\Debug\ErrorHandler.php:
What I've Tried
I've been debugging this for the last several days and have read many related discussions on Stack Overflow. I'm fairly new to services, subscribers, and dependency injection and I've tried editing both the routes.yml and services.yml numerous times. I was also getting some circular reference exceptions before but think I've fixed those now. I was hoping someone could please provide me with some direction and hopefully help me turn this into a working example on Symfony 3.3 that I can learn from. If you need any additional detail, please let me know.
From what I've learned, autowiring/autoconfiguring of services in Symfony 3.3 seems to be new and I think that may be impacting things but I'm not sure. I did try turning both of those settings off in services.yml though but with no luck.

RESTEasy cannot take in #PathParam typed Long

I have seen in tutorial (Jersey) that there is possibility to pass in JAX-RS #PathParam of type Long.
But when I have tried to do this with RESTEasy I'm getting error:
21:50:32,353 WARN [org.jboss.resteasy.core.ExceptionHandler] (default task-15) failed to execute: javax.ws.rs.NotSupportedException: Could not find message body reader for type: long of content type: */*
at org.jboss.resteasy.core.interception.ServerReaderInterceptorContext.throwReaderNotFound(ServerReaderInterceptorContext.java:52)
at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.getReader(AbstractReaderInterceptorContext.java:73)
I tested it with Integer, but it also don't work...
22:14:45,590 WARN [org.jboss.resteasy.core.ExceptionHandler] (default task-18) failed to execute: javax.ws.rs.NotSupportedException: Could not find message body reader for type: class java.lang.Integer of content type: */*
at org.jboss.resteasy.core.interception.ServerReaderInterceptorContext.throwReaderNotFound(ServerReaderInterceptorContext.java:52)
Moreover I am trying to take this ID value as String and then convert it to Long using Long.valueOf(String s) or Long.parseLong(String s) and in both cases I am getting error
Caused by: java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:601)
at java.lang.Long.parseLong(Long.java:631)
at pl.salonea.jaxrs.UserAccountResource.getUserAccount(UserAccountResource.java:41)
It's the code of my web service resource method:
#GET
#Path("/{userId}")
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public UserAccount getUserAccount(#PathParam("userId") String userId) {
return userAccountFacade.find(Long.parseLong(userId));
}
SOLVED
I have bad import not import javax.ws.rs.PathParam;, but something from web sockets PathParam... I just relay on IntelliJ automatic imports and haven't seen that it was wrong.