pathParameters documentation exception (urlTemplate not found) - java

When using pathParameters to document the URI path parameters like below
#Test
public void documentGetRouteById() throws Exception {
this.mockMvc.perform(get("/route/{id}", "FooBar")).andExpect(status().isOk())
.andDo(document("api-getRouteById",
pathParameters(parameterWithName("id").description("die Routen ID"))));
}
I get the following excpetion
java.lang.IllegalArgumentException: urlTemplate not found. Did you use RestDocumentationRequestBuilders to build the request?
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.restdocs.request.PathParametersSnippet.extractUrlTemplate(PathParametersSnippet.java:95)
at org.springframework.restdocs.request.PathParametersSnippet.extractActualParameters(PathParametersSnippet.java:82)
at org.springframework.restdocs.request.AbstractParametersSnippet.verifyParameterDescriptors(AbstractParametersSnippet.java:77)
at org.springframework.restdocs.request.AbstractParametersSnippet.createModel(AbstractParametersSnippet.java:65)
at org.springframework.restdocs.request.PathParametersSnippet.createModel(PathParametersSnippet.java:67)
at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:64)
at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:101)
at org.springframework.test.web.servlet.MockMvc$1.andDo(MockMvc.java:158)
I am pretty sure I did the test setup like explained here.
What could I probably have done wrong?
(Spring REST docs version is 1.0.0.BUILD-SNAPSHOT)

The exception message is trying to point you in the right direction:
urlTemplate not found. Did you use RestDocumentationRequestBuilders to build the request?
You need to use RestDocumentationRequestBuilders so that Spring REST Docs can capture the URL and extract the parameters from it. This is mentioned in the documentation where it says:
To make the path parameters available for documentation, the request must be built using one of the methods on RestDocumentationRequestBuilders rather than MockMvcRequestBuilders.
Replacing your static import of MockMvcRequestBuilders.get with one for RestDocumentationRequestBuilders.get should resolve the problem.

Related

Unable to create camel salesforce endpoint

I am trying to connect to salesforce using Apache Camel salesforce component.
Here is a very simple route I am trying to start:
#Override
public void configure() throws Exception {
from("salesforce:event/Case__e")
.to("mock:end");
}
When trying to start it I am getting an obvious error saying I did not specify a client id:
Caused by: java.lang.IllegalArgumentException: clientId must be specified
at org.apache.camel.util.ObjectHelper.notNull(ObjectHelper.java:149) ~[camel-util-3.16.0.jar:3.16.0]
at org.apache.camel.component.salesforce.SalesforceLoginConfig.validate(SalesforceLoginConfig.java:238) ~[camel-salesforce-3.16.0.jar:3.16.0]
That makes perfectly sense as according to Camel docs clentId parameter must be specified. To address this I am specifying a clientId as below:
#Override
public void configure() throws Exception {
from("salesforce:event/Case__e?clientId=xyz")
.to("mock:end");
}
When trying to start the route this time I am getting a rather strange error complaining about clientId being an unknown parameter:
Failed to resolve endpoint: salesforce://event/Case__e?clientId=xyz due to: There are 1 parameters that couldn't be set on the endpoint.
Check the uri if the parameters are spelt correctly and that they are properties of the endpoint.
Unknown parameters=[{clientId=xyz}]
Not sure what I am doing wrong and how should I address this.
Thank you in advance for your inputs.
Your problem is related to the fact that clientId is a component option so it must be configured at the component level while you try to configure it like it was a query parameter / an endpoint option which cannot work.
Depending on the runtime that you use, the way to configure a component may change but the idea remains the same.
For example, assuming that you use an application.properties to configure your application, the configuration of your salesforce component would look like this:
In application.properties
# Salesforce credentials
camel.component.salesforce.login-config.client-id=<Your Client ID>
camel.component.salesforce.login-config.client-secret=<Your Client Secret>
camel.component.salesforce.login-config.refresh-token=<Your Refresh Token>
...
Here is a salesforce example https://github.com/apache/camel-examples/blob/main/examples/salesforce-consumer/

Spring boot #PathVariable Validation

In my controller I have a ethod annotated by GetMapping and I want to validate the path variable. I tested the #max and #min. they were ok. but the thing is when I want to check when no path variable is not passed, I get 404 error code. meaning that i want to test the case like:
http://localhost:9090/api/mancala-game/last-state/
where there is nothing after the last /.
I want to get the exception in my ExceptionHandler class.
any ideas?
thank you
You should send path variable , in the url it self otherwise you will throw 404 error .
when your are not sending path variable it will be a different API:
in your case : http://localhost:9090/api/mancala-game/last-state/
and this url is not pointing to any handling method in your controller, So you will get 404 error.
I think http://localhost:9090/api/mancala-game/last-state/ and
http://localhost:9090/api/mancala-game/last-state/{key} is two api.
you can create /last-state and /last-state/{key}
What you want to do is add a wildcard ** at the end of the REST endpoint api/mancala-game/last-state/ at the place where you call the antMatchers() method for this REST endpoint. For example:
.authorizeRequests().antMatchers(HttpMethod.GET, "api/mancala-game/last-state/**").permitAll() //Other antMatchers after this..

multiple parameters with no annotation error on Javax WS and retrofit when I use "suspend" , how to handle?

I am creating a very basic controller using Kotlin with javax.ws and retrofit libraries.
I created a controller like this...
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
suspend fun sayHello(request: StudentRequest): StudentResponse {
that basically calls another service.
But when I run the app I get this error:
[FATAL] Method public final java.lang.Object MyResource.sayHello(StudentRequest,kotlin.coroutines.Continuation) on resource class MyResource contains multiple parameters with no annotation. Unable to resolve the injection source.;
handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor#a0bf272]},
definitionMethod=public final java.lang.Object my.org.package.MyResource(sayHello,k**otlin.coroutines.Continuation**),
the weird part is that are couple of similar posts Jersey #PathParam : contains multiple parameters with no annotation
How can I pass multiple parameter to restful webservice using http post
https://github.com/dropwizard/dropwizard/issues/1115
but are not the same because my problem is with my ONLY parameter
There is no missing tag to my body request and I basically dont know what to look for at this point, any idea what could be wrong with this?
After debugging I noticed that there are two parameters, mine and one injected by Kotlin, when removing the "suspend" everything works fine, but then I am not able to make my async call.
To use coroutines from blocking code you need to use coroutine builder (e.g. launch {} or runBlocking {}).
Unfortunately in this case you can't just mark your glassfish controller as a suspendable function because framework don't know how to deal with continuations.

How to access kerberos SPNEGO authenticated resource using spring rest template

I am running into issues while trying to access kerberos SPNEGO authenticated resource using spring rest client. I am using KerberosRestTemplate.
From the docs
Leave keyTabLocation and userPrincipal empty if you want to use cached ticket.
But while I try with invoking the parameterless constructor
this.kerberosRestTemplate = new KerberosRestTemplate();
And try to access to the protected resource it fails with the following error:
org.springframework.web.client.RestClientException: Error running rest call; nested exception is java.lang.IllegalArgumentException: Null name not allowed
at org.springframework.security.kerberos.client.KerberosRestTemplate.doExecute(KerberosRestTemplate.java:196)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:538)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:245)
Caused by: java.lang.IllegalArgumentException: Null name not allowed
at sun.security.krb5.PrincipalName.<init>(PrincipalName.java:356) ~[?:1.7.0_67]
at javax.security.auth.kerberos.KerberosPrincipal.<init>(KerberosPrincipal.java:123) ~[?:1.7.0_67]
at org.springframework.security.kerberos.client.KerberosRestTemplate.doExecute(KerberosRestTemplate.java:182)
What am I doing wrong here?
Please try these spring-security-kerberos. I think you are missing basic configuration which can be achieved either via xml or java configuration based .
Can also try following options:
Use loginOptions if you want to customise Krb5LoginModule options.
Use a customised httpClient.
Just call the constructor with null for keyTabLocation and any non-empty string for userPrincipal, like this:
KerberosRestTemplate restTemplate = new KerberosRestTemplate(null,"-");

Handling invalid URL's when using #ParamValue in Spring MVC

I am using #ParamValue annotation in my controller (Spring MVC).
Say My valid URL's are:
www.temp.com/test/a,
www.temp.com/test/b and
www.temp.com/test/c
So, my RequestMapping is:
#RequestMapping(value = "/test/{value}", method = RequestMethod.GET)
Now, my problem is that if anyone types a wrong URL like this :
www.temp.com/test/youarebroken
then I have to manually handle such a case in my controller to show 404 or not found.
Isn't there something inbuilt that sends a "not found or 404" notification to server that I can use directly ?
The simplest solution is to define a custom exception handler and to throw the custom exception when a validation fails within your controller. That would require that you manage the conditions manually as you stated you do not want to do.
A different solution is to use a global exception handler and define it to deal with the HTTP errors that are handled by Spring built-in.
In this link you can see both approaches: http://www.journaldev.com/2651/spring-mvc-exception-handling-exceptionhandler-controlleradvice-handlerexceptionresolver-json-response-example
However, from your question I understand you would like to return automatically an exception when certain condition in your param value does not meet, and you do not want to validate this manually within your controller. For this, you can add custom validation for an specific class and then set #Valid before the #ParamValue.
You can check this link for DataBinding http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
And this link for specific validation on param attributes: Spring Web MVC - validate individual request params
So, in plain a solution would be to define a custom validator that throws a custom exception when fails. To set #Valid for the parameters (check link) and to adjust the custom exception to handle HTTP errors (e.g. HttpStatus.NOT_FOUND).
You can use a regex in your #RequestMapping URL. Example:
#RequestMapping(value = "/test/{value:[a-z]}", method = RequestMethod.GET)

Categories