How and Where to use failOnUndocumentedParams in Spring Auto REST Docs? - mockmvc

I am working with Spring Auto REST Docs, and want to know the use of failOnUndocumentedParams, and how to use it. I want that documentation should not be generated if I miss a field from the POJO. I believe using failOnUndocumentedParams is my solution. However, I don't know how and where to use it.
#Before
public void setUp() throws IOException {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.alwaysDo(JacksonResultHandlers.prepareJackson(objectMapper))
.alwaysDo(MockMvcRestDocumentation.document("{class-name}/{method-name}",
Preprocessors.preprocessRequest(),
Preprocessors.preprocessResponse(
ResponseModifyingPreprocessors.replaceBinaryContent(),
ResponseModifyingPreprocessors.limitJsonArrayLength(objectMapper),
Preprocessors.prettyPrint())))
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation)
.uris()
.withScheme("http")
.withHost("localhost")
.withPort(8080)
.and().snippets()
.withDefaults(CliDocumentation.curlRequest(),
HttpDocumentation.httpRequest(),
HttpDocumentation.httpResponse(),
AutoDocumentation.requestFields(),
AutoDocumentation.responseFields(),
AutoDocumentation.pathParameters(),
AutoDocumentation.requestParameters(),
AutoDocumentation.description(),
AutoDocumentation.methodAndPath(),
AutoDocumentation.section()))
.build();
}
Here's how my mockMvc looks.

You can configure the feature when creating the request or response field snippets. In your case you want to enable the feature for all tests and thus when setting up Mock MVC:
.withDefaults(
...
AutoDocumentation.requestFields().failOnUndocumentedFields(true),
AutoDocumentation.responseFields().failOnUndocumentedFields(true),
...)
Alternatively one can enable the feature for a single test:
document("some-path",
AutoDocumentation.requestFields().failOnUndocumentedFields(true),
AutoDocumentation.responseFields().failOnUndocumentedFields(true))

Related

is there a way to mock internal service calls while writing Component testcases

I'm writing my component level test-cases for my repository. My API calls internally a third party API which I need to mock. I don't have direct access to that API neither I can directly call it, it needs to be called from within the API calls. I need to mock in order to run the component test-cases successfully. I tried wiremock but looks like it is not working and my API is still calling the 3rd party URL. Is there any way to solve this problem. Here is my code -
Annotation at class level
#Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8888));
WireMockServer wm;
Started server
#BeforeEach
void setUp() {
wm = new WireMockServer(WireMockConfiguration.options().port(8888));
wm.start();
}
In the tests.
wireMockServer.start();
wm.stubFor(get("https://someurl")
.willReturn(badRequest()
.withHeader("Content-Type", "application/json")
.withBody("<response>SUCCESS</response>")));
MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders
.post(apiContextPath)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(gson.toJson(offerParams)))
.andExpect(status().isOk()).andReturn();
wireMockServer.stop();
Sorry can't paste whole code due to security reasons.
It looks like you're trying to use the JUnit 4 rule with JUnit 5, meaning the WireMock server won't be started.
Try the JUnit Jupiter extension instead: https://wiremock.org/docs/junit-jupiter/

How to validate RestTemplate response?

Spring supports annotation based validation at the controller level.
(1) Is it necessary to do such validations also at the RestTemplate level for responses from REST calls?
If the answer is Yes:
(2) Will there be support for that at the RestTemplate to validate responses from rest calls sometime in the future?
If the answer is No:
(3) why?
It is 2020 now and I still do not see the requested feature in place.
The #Valid is nice to automatically validate e.g. a posted RequestBody.
But for the validation of the body of a ResponseEntity fetched via RestTemplate, I do not see any fancy equivalent.
So the only option I know, is to do it on your own taken from here. Input is the class of your RequestEntitys body. input is the body itself.
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Input>> violations = validator.validate(input);
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
So to answer your question:
Yes I would validate the response!
future (2020) has not brought the feature you and I miss
For the reason why this is missing, I also have no answer.
For me, the questions are quite big. :). As my understanding, you would like to ask the validation in REST service that Spring can support.
1. Is it necessary to do such validations also at the RestTemplate level for responses from REST calls?
Actually, it depends on your apps or your business. You can do at Controller or you can do in Service Level or even you can do your custom validation. For me, no one forces you to do anything.
However, as my experience, we should do the validation for sure. So my answer here is YES.
2. Will there be support for that at the RestTemplate to validate responses from rest calls sometime in the future?
I assume that you would like the detail of the validation?! Right?
Spring supports many things to do the validation. For the simple way, you can use PathVariable or RequestParameter.For example:
#GetMapping("/test/{name}")
private String test(#PathVariable(value = "name", required = true) String name){
//...
}
Spring will validate all requests, and respond with 400 Bad Request when the required parameter is missing or has a wrong type...
Spring also supports the JSR 303 Bean Validation: http://beanvalidation.org/1.0/spec/ For example in here:
public class MessageBean {
#NotNull
private String title;
#NotNull
private String message;
// getters/setters/etc
}
Or you would like to do the Custom User Response like:
#ExceptionHandler
#ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleException(MethodArgumentNotValidException exception) {
//....
return ErrorResponse.builder().message(errorMsg).build();
}
Some more details in here: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-validation
So, it depends on the business which requires us to do the validation at any level.
3. If the answer is No: (3) why?
No need to answer this. :)
Hope that helps

Olingo OData V2 Read Property not implemented

I implemented an OData V2 Service with Apache Olingo V2 in connectin with JPA using EclipseLink. All requests are working fine, but when it comes to the point, where I want to access a single property via GET request from an entity set like for the following URL:
http://localhost:8080/MyODataService/XXXXXX.svc/EntitySet(12345)/Property
the response in return is:
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code/>
<message xml:lang="de-DE">Not implemented</message>
</error>
The class which extends the ODataJPASeviceFactory looks as follows:
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAServiceFactory;
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
public class JPAODataServiceFactory extends ODataJPAServiceFactory
{
private static final String PERSISTENCE_UNIT_NAME = "MyPersistenceUnitName";
#Override
public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException
{
ODataJPAContext oDatJPAContext = this.getODataJPAContext();
try
{
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
oDatJPAContext.setEntityManagerFactory(emf);
oDatJPAContext.setPersistenceUnitName(PERSISTENCE_UNIT_NAME);
return oDatJPAContext;
} catch (Exception e)
{
throw new RuntimeException(e);
}
}
My question now is:
How do I implement the functionality, so that I can do GET and POST requests not only for a whole entity set, but also for a single property of an entity set like I tried with the mentioned URL?
Accessing a single property from one entity is currently not implemented if you use the Olingo JPA Extension.
If you want to support this behaviour you can register a custom processor and only override the "readEntityComplexProperty" and "readEntitySimpleProperty" methods. There you can have your custom code where you specifically get back the value.
Every method you don`t override will result in the standard Olingo functionality being executed.
Here is a tutorial on how to register a custom JPA processor: http://olingo.apache.org/doc/odata2/tutorials/CustomODataJPAProcessor.html
Here is the example on how your code can look like if you implement the functionality yourself: https://github.com/apache/olingo-odata2/blob/597465569fdd15976d0486711d4a38f93a7c6696/odata2-lib/odata-ref/src/main/java/org/apache/olingo/odata2/ref/processor/ListsProcessor.java#L592
You need to create an association between your entity sets.
For example, to access the following URL: http://localhost:8080/myService.svc/Cars('6')/Manufacturer, you need to create an assocation between your car and your manufacturer association sets.
Have a look at the documentation: https://olingo.apache.org/doc/odata2/tutorials/basicread.html
Hegg,
you can use
http://localhost:8080/MyODataService/XXXXXX.svc/EntitySet(12345)/?$select=Property
Bye
Domenico

Questions about combining Hystrix with Feign

I am trying to use the new HystrixFeign support in Feign. Here is what my code looks like
route66Client =
HystrixFeign.builder()
.logger(new Slf4jLogger())
.encoder(new GsonEncoder())
.target(Route66Client.class, "http://route66/");
The Route66Client is defined as
public interface Route66Client {
#RequestLine("POST /route")
ApiResponse getRoute(
RouteRequest request);
}
When i try to run the code. I get UnknownHostException. As it is not able to resolve route66 for its hostname. Anyone knows what i could be missing ?
Further i had this working with regular Feign ( not HystrixFeign ). All i did was to annotate my Route66Client class with #FeignClient("...") and then injecting Route66Client in the calling class ( So no Feign.builder() was used )
But i couldn't find some #HystrixFeignClient annotation. So i went ahead and started using the HystrixFeign.builder(). But then when i did that the serviceName->Address resolution stopped working.
If you want the benefits of eureka, don't use the builder directly. Put #EnableFeignClients on an #Configuration class (usually your application). Then label Route66Client with #FeignClient("route66") and inject Route66Client. This is only available in Brixton's 2nd Milestone. See the documentation.

Send localized email in GWT [duplicate]

I have an interface that extends the com.google.gwt.i18n.client.Messages class, which I use for retrieving i18n messages in my GWT application. It looks like this:
public interface MyMessages extends com.google.gwt.i18n.client.Messages {
#DefaultMessage("Hello world")
#Key("message1")
String message1();
#DefaultMessage("Hello again")
#Key("message2")
String message2();
//...
}
Normally, I create an instance of it using GWT.create() like so:
private MyMessages messages = GWT.create(MyMessages.class);
However, this does not work with server-side code, only client-side code (it throws an error saying that GWT.create() is only usable in client-side code).
The answer to a similar question points to a separate library that you can download which will let you access the i18n messages on the server, but I don't want to download any extra libraries (this seems like a simple problem, there must be a simple solution).
In summary: How can I access my i18n messages in server-side code? Thanks.
On the server side you can use the standard Java localization tools like ResourceBundle.
Look here for a tutorial how to use it.
// Create a ResourceBundle out of your property files
ResourceBundle labels =
ResourceBundle.getBundle("LabelsBundle", currentLocale);
// Get localized value
String value = labels.getString(key);
The GWT specific way of creating an interface out of your property files and providing implementations via deferred binding can not be used on sever side Java.
If you are fearless and willing to spend the time, you can implement a code generation step to read your property files and generate implementation classes for your message interface. That's exactly what the Google GWT compiler does behind the scene.
I agree with Michael.. I was having this problem of trying to "localize" messages generated on the server.... but I decided to instead just throw an Exception on the server (because it is an error message which should only happen exceptionally) which contains the message code, which the client code can then look up and show the correct localized message to the user.
There's a great library for GWT internationalization gwt-dmesg. It allows you to 'share' .properties files between clent and server. However, project looks to be abandoned by author and you must recompile it manually for use with GWT versio >= 2.1.0.
GWT.create() can only be used in client-side code.
The good thing to do is that you provide your own I18NProvider class/interface, from which then you can extend to server side I18N factory and client side I18N factory read the same resource bundle.
After that you can simply use it all over your system, unify your code.
Hope that helps.
Following vanje's answer, and considering the encoding used for the properties files (which can be troublesome as ResourceBundle uses by default "ISO-8859-1", here is the solution I came up with:
import java.io.UnsupportedEncodingException;
import java.util.Locale;
import java.util.ResourceBundle;
public class MyResourceBundle {
// feature variables
private ResourceBundle bundle;
private String fileEncoding;
public MyResourceBundle(Locale locale, String fileEncoding){
this.bundle = ResourceBundle.getBundle("com.app.Bundle", locale);
this.fileEncoding = fileEncoding;
}
public MyResourceBundle(Locale locale){
this(locale, "UTF-8");
}
public String getString(String key){
String value = bundle.getString(key);
try {
return new String(value.getBytes("ISO-8859-1"), fileEncoding);
} catch (UnsupportedEncodingException e) {
return value;
}
}
}
The way to use this would be very similar than the regular ResourceBundle usage:
private MyResourceBundle labels = new MyResourceBundle("es", "UTF-8");
String label = labels.getString(key)
Or you can use the alternate constructor which uses UTF-8 by default:
private MyResourceBundle labels = new MyResourceBundle("es");