Spring boot validation only working with #valid: - spring

My Spring Boot validation only works if I use the annotation like this (I use Kotlin):
#valid:NotEmpty(message = "Please enter a value")
So for example:
data class RandomDto(
#valid:NotEmpty(message = "Please enter a value")
var randomValue: String
)
If I use this it won't work:
#NotEmpty(message = "Please enter a value")
Why is this? I annotated the controller function parameter with #Valid.
Thanks in advance.

I think it is a dependency issue. make sure to add the following dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Related

Argument passed to when() is not a mock! exception thrown with Spring Boot project which doesn't have #SpringBootApplication/main class

My project is a simple spring boot application which doesn't have a main/#SpringBootApplication class. It is used as a dependency library for other modules. I am trying to write the unit tests for the classes present in this project like below and getting the below pasted error. Any quick help is much appreciated.
pom dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- exclude junit 4 -->
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- junit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
As this project doesn't have main class, to get the spring application context using below configuration class.
#Configuration
public class TestServiceConfig {
#Bean
public TestService productService() {
return Mockito.mock(TestService.class);
}
#Bean
public MongoDriverService productMongo() {
return Mockito.mock(MongoDriverService.class);
}
}
Below is my test class which is throwing exception. Actual java class has a method called getPlanCode(which takes 6 arguments) and returns void. In this method mongo object is used for connecting the db so that I used #InjectMocks on service object.
public class ValidationServiceTest {
#Mock
MongoDriverService mongo;
#InjectMocks
TestService service;
#Test
#DisplayName("Test Get Plan Code positive")
public void getPlanCodeTest() {
doNothing().when(service).getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());
service.getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());
verify(service, times(1)).getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());
}
}
Below is the exception
12:51:33.829 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - After test method: context [DefaultTestContext#45b4c3a9 testClass = DefaultMedicareBFTAccumsValidationServiceTest, testInstance = com.anthem.rxsmart.service.standalone.batchvalidation.DefaultMedicareBFTAccumsValidationServiceTest#14dda234, testMethod = getPlanCodeTest#DValidationServiceTest, testException = org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!
Example of correct stubbing:
service is not a mock since you are using #InjectMocks ( assume you are using #RunWith(MockitoRunner.class) or #ExtendWith but you are hiding that for whatever reasons).
What #InjectMocks does, is create of a new instance of TestService and literally inject mocks into it (mocked required dependencies). So service is a real thing, not a mock
IMO this test makes not sense as you are suppose to test your implementation of singular entity contract, not to test mocks...
Your test case and assertions are pointless as it is like "call method A and check if I just called method A" while you should check and validate eg return value of a call, or if some methods of mocks have been called eg if Mongo was queried with proper arguments. I just hope it is a really bad example, not real test scenario
Also test setup is wrong as you show us that you want to use #Configuration class with #Bean but then you are using #Mock in the test which will create brand new mocks for you. In other words - that config is not used at all
Posting this answer just for the developers who are in same understanding state.
#Test
#DisplayName("Test Get Plan Code positive")
public void getPlanCodeTest() {
service = new ValidationService(mongo);
Mockito.when(mongo.aggregateIterable("test", pipeline)).thenReturn(tierFilterDocs);
service.getPlanCode("", "", null, batchFile, null, "");
verify(mongo, times(1)).aggregateIterable("test", pipeline);
}
I have updated my test case so it solves the purpose now. Now no need of the Configuration file as I am mocking the object in test class itself.

Configure HTTPS in Spring Boot Apache Camel REST API with keystore having multiple certs using camel-jetty component

I am trying to configure https in my apache camel Spring Boot REST application (using apache-camel v3.11.1, springboot v2.5.3) with keystore having multiple certificates.
Problem:
Application run failed
org.apache.camel.RuntimeCamelException: java.lang.IllegalStateException: KeyStores with multiple certificates are not supported on the base class org.eclipse.jetty.util.ssl.SslContextFactory. (Use org.eclipse.jetty.util.ssl.SslContextFactory$Server or org.eclipse.jetty.util.ssl.SslContextFactory$Client instead)
at org.apache.camel.RuntimeCamelException.wrapRuntimeCamelException(RuntimeCamelException.java:51) ~[camel-api-3.11.1.jar:3.11.1]
Project setup:
pom.xml: (dependencies only, to show that I am not using spring-boot-web-starter)
..
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jetty-starter</artifactId>
</dependency>
..
..<!-- all other required dependencies are in place-->
..
</dependencies>
..
application.properties
#camel.component.jetty.keystore=keystore-with-one-certificate.jks # WORKS
camel.component.jetty.keystore=keystore-with-multiple-certificates.jks # DOESN'T WORK
camel.component.jetty.ssl-key-password=password
camel.component.jetty.ssl-password=password
Rest Route:
restConfiguration()
.component("jetty")
.scheme("https")
.port("8080");
rest()
.path("/api")
.get("/{name}")
..
..
.to("direct:x");
Looked at answers in the below posts, but still not able to resolve the exception that I get,
https://stackoverflow.com/a/60598953/6363894,
https://stackoverflow.com/a/55499113/6363894
I know that exception clearly states to use org.eclipse.jetty.util.ssl.SslContextFactory$Server, but I don't understand how/where to use SslContextFactory.Server object.
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(findKeyStorePath());
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setKeyManagerPassword("password");
sslContextFactory.setNeedClientAuth(true);
Also I've created a bean for sslContextParameters and added that to restConfiguration as below, this time application runs successfully but then when I test, SSL handshake fails.
restConfiguration()
.component("jetty")
.endpointProperty("sslContextParameters", "#sslContextParameters")
.scheme("https")
.port("8080");
#Bean(name = "sslContextParameters")
public SSLContextParameters setSSLContextParameters() {
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("keystore-with-multiple-certificates.jks");
ksp.setPassword("password");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("password");
SSLContextServerParameters scsp = new SSLContextServerParameters();
scsp.setClientAuthentication("REQUIRE");
SSLContextParameters scp = new SSLContextParameters();
scp.setServerParameters(scsp);
scp.setKeyManagers(kmp);
return scp;
}
Any help on how to configure SslContextFactory.Server object with the restConfigurations() or any other way I can achieve this? I'll update the post, if any more details are required.

Connecting Springboot application to Azure databricks

I'm trying to connect SpringBoot Application to Azure Databricks.
Below is something I have tried....
application.properties
spring.datasource.url = jdbc:spark://adb-**********.*.azuredatabricks.net:**/default;transportMode=http;ssl=1;httpPath=sql/protocolv1/o/******/******-*****-abcd341
spring.datasource.username = username
spring.datasource.password = Generated Token
pom.xml
Below are some dependencies I'm using...
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.10</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.10</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.databricks</groupId>
<artifactId>spark-avro_2.10</artifactId>
<version>2.0.1</version>
</dependency>
I'm getting below error..
***************************
APPLICATION FAILED TO START
***************************
Description:
Cannot determine embedded database driver class for database type NONE
Action:
If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
Suggest me if I'm missing any maven dependency.
Thanks in Advance..
To connect from the Spring Boot you need to use JDBC driver, not Spark jars (remove them - you don't need them). You can get JDBC driver as described in documentation, or very recently - directly via Maven using following coordinates:
<dependency>
<groupId>com.databricks</groupId>
<artifactId>databricks-jdbc</artifactId>
<version>2.6.25-1</version>
</dependency>
and then use standard JDBC APIs exposed by Spring. I have a simple example that uses JdbcTemplate to access data in Databricks - you just need to construct JDBC URL correctly:
String host = "";
String httpPath = "";
String token = "";
String jdbcUrl = "jdbc:databricks://" + host +
":443/default;transportMode=http;ssl=1;httpPath=" +
httpPath + ";AuthMech=3;UID=token;PWD=" + token;
and then just access data:
// define data source
SimpleDriverDataSource ds = new SimpleDriverDataSource();
ds.setDriver(new Driver());
ds.setUrl(jdbcUrl);
JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
// query data
List<Map<String, Object>> data = jdbcTemplate.queryForList(query);
for (Map<String, Object> row: data) {
....
}
P.S. You may omit username or at least set it to the token value...
Try adding the "spring.datasource.driverClassName" , and let me know if that helps you to proceed

Object distortion while passing from REST service to Spring app

I've got strange problem and I hope you will to help me to solve it.
I try to pass list of objects, where each object contains LocalDate parameter (JodaTime library) from test service to my controller.
This is method from my service. It returns list of objects. Look at the dates printed out in the loop.
#RequestMapping("/getListaRecept")
#ResponseBody
public ListaRecept sendAnswer(){
ListaRecept listaReceptFiltered = prescriptionCreator.createListaRecept();
for(Recepta r : listaReceptFiltered.getListaRecept()){
System.out.println(r.toString());
}
return listaReceptFiltered;
}
Dates are correct
Recepta{id=3, nazwa='nurofen', status=NOT_REALIZED, date=2017-07-27}
Recepta{id=1, nazwa='ibuprom', status=ANNULED, date=2014-12-25}
Recepta{id=2, nazwa='apap', status=REALIZED, date=2016-08-18}
And now I'm invoking this method from my SpringBoot app using restTemplate. And then received list is printed out
private final RestTemplate restTemplate;
public SgrService2(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
this.restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-16")));
}
public ListaRecept getList() {
for(Recepta r : this.restTemplate.getForObject("http://localhost:8090/getListaRecept",
ListaRecept.class).getListaRecept()){
System.out.println(r.toString());
}
return this.restTemplate.getForObject("http://localhost:8090/getListaRecept",
ListaRecept.class);
}
As you can see all dates were replaced with current date :/
Recepta{id=3, nazwa='nurofen', status=NOT_REALIZED, date=2017-09-30}
Recepta{id=1, nazwa='ibuprom', status=ANNULED, date=2017-09-30}
Recepta{id=2, nazwa='apap', status=REALIZED, date=2017-09-30}
I have no idea what is going on...
Here you have pom dependencies
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.1</version>
</dependency>
Thank you in advance for your help
It seems to me that you are using the wrong jackson module, instead of jsr310 (which I guess is for Java 8 date types), try using the artifact jackson-datatype-joda and register the module JodaModule.

Testing with spring-test-mvc jsonpath returns null

I am using Spring's "spring-test-mvc" library to test web controllers. I have a very simple controller that returns a JSON array. Then in my test I have:
#Test
public void shouldGetAllUsersAsJson() throws Exception {
mockMvc.perform(get("/v1/users").accept(MediaType.APPLICATION_JSON))
.andExpect(content().mimeType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("fName").exists());
}
The above test returns:
java.lang.AssertionError: No value for JSON path: fName
To quickly check what I actually get I ran the below test:
#Test
public void shouldPrintResults() throws Exception {
mockMvc.perform(get("/v1/users").accept(MediaType.APPLICATION_JSON))
.andDo(print());
}
And it returns the correct JSON array in the body of MockHttpServletResponse
I'm not sure why jsonPath is not able to see fName in the JSON array.
If you add the json path dependency to maven, or add the jar to your lib, then it will work. I think that Spring is not including the jsonPath dependency in the latest Spring 3.2.0 RC1 release. I'm guessing that this is the same for Spring-Test-MVC standalone project as well.
Here is the dependency for Maven:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>0.8.1</version>
<scope>test</scope>
</dependency>
You might also need the hamcrest library to use the jsonPath("$.test").value("test")
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
What does your json response body look like? You can see it by doing an .andDo(print())
You might want to try jsonPath("$.fName").
This is assuming that your json response is:
{"fName":"first name"}
If your response is an array then you need jsonPath("$[0].fName") for a response like:
[{"fName":"first name"},{"fName":"first name #2"}]
You can see more examples at: http://goessner.net/articles/JsonPath/

Resources