I am using swagger-codegen-maven-plugin to generate an api rest client. I am using the resttemplate library and my pom.xml configuration looks like the following.
<build>
<plugins>
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/../swagger.yml</inputSpec>
<language>java</language>
<generateApis>true</generateApis>
<generateApiTests>false</generateApiTests>
<generateSupportingFiles>true</generateSupportingFiles>
<generateModelDocumentation>false</generateModelDocumentation>
<modelPackage>my.base.package.here</modelPackage>
<apiPackage>my.base.api.package.here</apiPackage>
<modelNamePrefix>MyApiPrefix</modelNamePrefix>
<configOptions>
<library>resttemplate</library>
<sourceFolder>src/gen/java</sourceFolder>
<java8>true</java8>
<dateLibrary>java8</dateLibrary>
<hideGenerationTimestamp>true</hideGenerationTimestamp>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The client generation works sucessfully. Now I am using this client in a spring boot app and I need to configure the connection timeout and the read timeout values.
I was surprised to find no setters for these two properties on the generated ApiClient. So I had to come out with a workaround that uses the RestTemplateBuilder to do that. It looks like this:
#Configuration
public class MyApiClientConfiguration {
#Autowired
public MyApiClientConfiguration(
final RestTemplate restTemplate,
final RestTemplateBuilder restTemplateBuilder
) {
restTemplateBuilder
.setConnectTimeout(connectTimeoutValue)
.setReadTimeout(readTimeoutValue)
.configure(restTemplate);
ApiClient apiClient = new ApiClient(restTemplate);
MyApiPrefixApi.setApiClient(apiClient);
}
}
The doc for the configure method does not say much:
configure
public T configure(T restTemplate)
Configure the provided RestTemplate instance using this builder.
Is this the standard approach to configure timeouts when using the resttemplate library? UPDATE: My actual implementation does not work (it seems the ResttemplateBuilder own configurations are interfering in a wrong way with the autowired RestTemplate (that I am trying to further configure through the builder)) configuration. The api client generated by other libraries (such as jersey for example) provide a setter to directly configure the timeout using:
apiClient.setConnectTimeout(timeoutValue);
Though the use of the configure method does not work, it is possible to configure the timeout values by creating a RestTemplate bean using the RestTemplateBuilder's build method.
#Bean
public RestTemplate restTemplate(
RestTemplateBuilder restTemplateBuilder,
final int serviceConnectionTimeout,
final int serviceReadTimeout
) {
return restTemplateBuilder
.setConnectTimeout(serviceConnectionTimeout)
.setReadTimeout(serviceReadTimeout)
.build();
}
Ref: Spring RestTemplate timeout
Related
I am using OpenApi(3.0) for api definition and the openapi-generator-maven-plugin which generates files for me (api objects + endpoints).
Its however generating a test file in the build folder that I do not want. Its called 'OpenApiGeneratorApplicationTests'. It always blocks my compilation bc in the 'target' (=build) folder I do not have the right Spring Boot setup.
How can I avoid the generation of this test file?
This is my maven config:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>6.0.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/ApiDef.yaml</inputSpec>
<generatorName>spring</generatorName>
<modelPackage>${clientPackage}.model</modelPackage>
<invokerPackage>${clientPackage}.invoker</invokerPackage>
<apiPackage>${clientPackage}.api</apiPackage>
<generateApis>true</generateApis>
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
<configOptions>
<delegatePattern>true</delegatePattern>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
I've encountered today the same issue. So long story short:
By default the generator maven plugin for Spring will generate the 'invoker' - which by implementation is actually a #SpringBootApplication starter class.
#SpringBootApplication
#ComponentScan(basePackages = {"com.mypackage.invoker", "com.mypackage.api" , "org.openapitools.configuration"})
public class OpenApiGeneratorApplication {
public static void main(String[] args) {
SpringApplication.run(OpenApiGeneratorApplication.class, args);
}
#Bean
public Module jsonNullableModule() {
return new JsonNullableModule();
}
}
and will also generate the associated test class OpenApiGeneratorApplicationTests
#SpringBootTest
class OpenApiGeneratorApplicationTests {
#Test
void contextLoads() {
}
}
The problem here is that the src/test/com/mypackage/invoker/OpenApiGeneratorApplicationTests.java, and actually the whole package under test is marked as source, not as test-source and in my case this will result in compile time errors (since the test-scoped dependencies are not found).
I managed to get around it by configuring the maven plugin with
<configOptions>
<interfaceOnly>true</interfaceOnly>
...
</configOptions>
which will skip the generation of the SpringBootApplication and the associated Tests.
I've also submitted a ticket to the OpenApi Generator project's github for marking the
I'm writing integration tests for project and I want to merge all database migration scripts into schema.sql before Spring picks it up to populate the database.
For this I use a small class that searches the project for sql files and merges them into one.
I've created a Suite like so:
#RunWith(Suite.class)
#Suite.SuiteClasses({MyTests.class})
public class SuiteTest {
#BeforeClass
public static void setUp() throws IOException {
RunMigrations.mergeMigrations();//this one merges all sqls into one file, called schema.sql
}
}
Then, here's my test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = App.class)
#ActiveProfiles(resolver = CustomActiveProfileResolver.class)
#ContextConfiguration(classes = App.class)
public class MyTests extends AbstractTransactionalJUnit4SpringContextTests {
#PostConstruct
public void before() {
mvc = MockMvcBuilders.webAppContextSetup(context).addFilter(springSecurityFilterChain).build();
}
#Test
#Transactional
public void Test1(){ //do stuff }
}
But this doesn't work as I thought it would. It looks like Spring tries to run schema.sql faster than I'm creating it and fails like this:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [application]
If I just turn off my code that generates schema.sql and let Spring run with already created schema then all is good. But if I delete schema.sql and let my class to generate it, then it fails as described.
I've tried to override run(RunNotifier notifier) method in SpringJUnit4ClassRunner and put my migration merger in there, before it calls super.run(notifier) method, but that still doesn't work.
Is there a way to generate that schema.sql before Spring gets its hands on it?
P.S.
I cannot use flyway for production environment. Perhaps it is possible using it just for tests?
UPD:
After some experimenting, I've set this in test.yml:
spring.jpa.hibernate.ddl-auto: none
Now it loads context, performs one test which just gets Oauth2 token and fails with other tests that perform POST and GET requests because it cannot execute #sql annotations that put additional data before test methods. The database seems to be untouched, that is without any tables whatsoever.
You can enable flyway just for tests either by using #TestPropertySource(properties = {"spring.flyway.enabled=true"}) annotation or by creating a test Spring profile with it's own property file. The latter would look like:
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles("test")
public MyTest {
with src/test/resources/application-test.yml file:
spring:
flyway:
enabled: true
and flyway-core as a test scoped dependency.
Do note that Flyway properties in Spring Boot were renamed in Spring Boot 2.0.
Perhaps someone may find this useful.
I managed to solve this by using exec-maven-plugin with failsafe plugin.
The test class setup remains the same, I only removed #BeforeClass annotation from Suite.
Here's the POM:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${org.apache.maven.plugins.maven-surefire-plugin-version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${org.apache.maven.plugins.maven-failsafe-plugin-version}</version>
<executions>
<execution>
<id>integration-test-for-postgres</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify-for-postgres</id>
<phase>verify</phase>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${org.codehaus.mojo.exec-maven-plugin-version}</version>
<executions>
<execution>
<id>build-test-environment</id>
<phase>generate-test-resources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<!--This class prepares the schema.sql file which is fed to Spring to init DB before tests.-->
<mainClass>...GenerateTestDBSchema</mainClass>
<arguments>
<argument>...</argument><!--the migration folder-->
<argument>...</argument><!--The path where to put schema sql-->
</arguments>
</configuration>
</plugin>
</plugins>
</build>
The GenerateTestDBSchema class has main method and uses args array to accept paths where to find migrations and where to put schema.sql.
public static void main(String[] args) {
try {
mergeMigrations(args[0], args[1]);
} catch (IOException e) {
LOG.error(e.getMessage());
}
}
The mergeMigrations() method is straightforward: just take all files from directory, merge them and write to output path. This way Spring has it's schema.sql before context is launched and it itself decides where to run migrations.
Thanks to #ActiveProfiles(resolver = CustomActiveProfileResolver.class) in integration test, spring resolves profiles and picks up application-{profileName}.yml and sets database address automatically.
i would like to integrate an Angular 4 client app with a Java Spring application working on http://localhost:8080/ and offering some Rest endpoints.
My goal is to be able to call the Angular app from a url like http://localhost:8080/adminisitration. How can I do that?
Thanks in advance,
You would need to prod build your ng app and place that in spring-boot folder:
Create a public folder under resources in your spring-boot project
ng build --prod, type this command on you angular project which will create a dist folder under your angular project directory
Copy files from you dist folder and place it in public folder under resources of your spring-boot project.
This will help you run your angular-app under spring-boot.
Then hit http://localhost:8080/adminisitration, it should work fine
There are two ways first is that you serve angular app from your spring boot application as static resources so you need to pack it into jar and that's not easy when you have two different repositories for frontend and backend and doesn't look to good from maintenance point of view.
Second is that you have angular static resources on nginx and spring boot app is reachable to angular thru reverse proxy configured on nginx like
location /api/ {
proxy_pass http://localhost:8080/api/;
}
So when angular asks for GET http://localhost/api/somerest it forwards it to GET http://localhost:8080/api/somerest
The easiest way to serve an angular front-end from a spring-boot application , is to have a multi-module project. Then automate the build process to copy the dist folder from the ui module into the service module during maven clean install itself.This way, you could have a single executable jar that serves the angular as well.For instance, consider the following project structure :
SampleMultiModuleProject
|__SampleMultiModuleService
|__SampleMultiModuleUI
In this case, you will have three different pom files like as follows.
SampleMultiModuleProject main pom.xml : (where all main dependencies are present)
<modules>
<module>SampleMultiModuleUI</module>
<module>SampleMultiModuleService</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
//add rest of the dependencies here.
SampleMultiModuleService service pom.xml : (for service module and add the springboot maven plugin to make it executable with embedded tomcat, and add other dependencies that are needed in service module , for instance lombok)
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
and finally configure the ui module to build angular like SampleMultiModuleUI pom.xml :
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.9.1</version>
<configuration>
<workingDirectory>./</workingDirectory>
<nodeVersion>v13.3.0</nodeVersion>
<npmVersion>6.13.1</npmVersion>
<nodeDownloadRoot>http://nodejs.org/dist/</nodeDownloadRoot>
<npmDownloadRoot>http://registry.npmjs.org/npm/-/</npmDownloadRoot>
<installDirectory>./</installDirectory>
<npmInheritsProxyConfigFromMaven>false</npmInheritsProxyConfigFromMaven>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm run-script build-prod</id>
<phase>prepare-package</phase>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run-script build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
So what happens is when you do maven clean install, it will trigger the build of the ui module which in turn uses the frontend builder to install a local npm which runs the command specified in the arguments. The package.json file in your angular application will by default contain something like :
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"stats": "webpack-bundle-analyzer dist/stats.json"
},
So you are essentially calling this ng build --prod through this process.Also in angular.json set the output path as the resources folder under the service module in your project, so that the assets will be created there.
"newProjectRoot": "projects",
"projects": {
"SampleMultiModuleUI": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"outputPath": "../SampleMultiModuleService/src/main/resources/static",
//rest of the config
as i understand your question just create new file named proxy.config.json and paste below code in that file, place file next to .angular-cli.json
{
"/": {
"target": "http://localhost:8080",
"secure": false,
"logLevel": "debug"
}
}
for hitting url to backend server don't use http://localhost:8080/administration instead use /administration as we use http://localhost:8080/ in our proxy file.
in app.component.ts file place below code in ngOnInit()
this.http.get('/adminisitration',someRequestOption).subscribe(res =>{
console.log('happy...!');
})
start backend server: (tomcat on port 8080) and
start frontend server:
ng serve --proxy-config proxy.config.json open browser and type url http://localhost:4200 you will see logs on server and client if any.
NOTE:
above ports are default as provided by spring boot and angular 4
I think best way is to separate angular 4 app and java spring app.
In my case java spring app is API handling all requests from angular 4 app via proxy (angular-cli proxy -> easy to configure).
Angular 4 app on node.js, developed in visual studio code, and java spring on embedded tomcat (undertow) developed in eclipse. They can be on separated servers (eg. my angular 4 app is on localhost:4200 while java spring API is on http://mydomain.ch:8900)
If you need more info then add comment.
Hope in helps
PS. proxy is handled on client side (angular 4 app) not on server side (java spring)
Should look like a stupid question, but I have the following problem.
There's an external web service, WSDL is available. My task is to call it's methods from another enterprise application (running on WebSphere 8.5)
Using Rational Application Developer, I generated Web service client classes into the application's project, specifying the application's package, which DIFFERS from the web service's one. Web service's method returns a POJO, which is a wrapper for ArrayList.Then I make a call to web service, using generated calsses in the following way:
package com.mycompany.services.external;
import com.mycompany.services.external.client.SomeCommonService;
import com.mycompany.services.external.client.SomeCommonServiceService;
import com.mycompany.services.external.client.IdsList;
final QName COMMONSERVICE_QNAME = new QName("http://webService.othercompany.com/", "SomeCommonServiceService");
String strUrl = "http://....";
String query = "/universal [#Barcode=\"000111\"]";
URL serviceUrl = new URL(strUrl);
SomeCommonServiceService service=new SomeCommonServiceService(serviceUrl, COMMONSERVICE_QNAME);
SomeCommonService port = service.getSomeCommonServicePort();
IdsList itemsIds = port.getItemsIdsByQuery(query);
And as a result the last line of code, where the method is invoked, causes an error:
[1/17/17 21:55:39:758 MSK] 00000497 SystemErr R CIWEB Error:
[admin(unknown) # 10.253.32.24]
com.ibm.ecm.util.PluginUtil.invokeService()
javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException:
com.mycompany.services.external.client.IdsList is not known to this
context
Taking a look into the generated package-info.java the following mapping can be seen:
#javax.xml.bind.annotation.XmlSchema(namespace = "http://webService.othercompany.com/")
package com.mycompany.services.external.client;
If I leave original option (not changing default package) while generating client - the same problem and the same error. But in this case, if I pack generated client into a separate JAR and use it as a shared library for my application on WebSphere server - then all works fine! But that's not acceptable for some reasons.
Could somebody be so pleasant to hepl me solve the problem?
I used to work with Web Services Base on WSDL:
Example: http://www.dgii.gov.do/wsMovilDGII/WSMovilDGII.asmx?wsdl
Of course using MAVEN, I use this pluging
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.1.5</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${basedir}/src/main/java/</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>http://www.dgii.gov.do/wsMovilDGII/WSMovilDGII.asmx?wsdl</wsdl>
<packagenames>
<packagename>com.hectorvent.consultadgii</packagename>
</packagenames>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
I want to use ihomefinder's test APIs to get the data and insert it into my own database. I am using Spring MVC and the link provided by them which I configured in my pom.xml to get the data is http://axisws.idxre.com:8080/axis2/services/IHFPartnerServices?wsdl.
From various searches I found that all the provided APIs are in package com.ihomefinder.api so I included it too into the pom.xml
Here is the pom.xml code:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-ws</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>com.ihomefinder.api</generatePackage>
<schemas>
<schema>
<url>http://axisws.idxre.com:8080/axis2/services/IHFPartnerServices?wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
</plugins>
</build>
Now I am trying to login with the test username and password provided by them, but to hit the login service I need to create the Object of Request class which is not found in the package com.ihomefinder.api.
Here is the java code I am using to make the request:
import javax.xml.bind.JAXBElement;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import com.ihomefinder.api.Login;
import com.ihomefinder.api.ObjectFactory;
public class IdxMls extends WebServiceGatewaySupport {
public void main() {
// TODO Auto-generated method stub
ObjectFactory objectFactory = new ObjectFactory();
JAXBElement<String> user = objectFactory.createLoginUsername("username");
JAXBElement<String> pass = objectFactory.createLoginPassword("password");
Login login = new Login();
login.setUsername(user);
login.setPassword(pass);
Integer int1 = (Integer) getWebServiceTemplate().marshalSendAndReceive(login, new SoapActionCallback("http://axisws.idxre.com:8080/axis2/services/Login"));
System.out.println(int1);
}
public static void main(String[] args) {
IdxMls idxMls = new IdxMls();
idxMls.main();
}
}
I think the above code is not perfect some things are really missing. So can anybody help me to correct the code by which I can get the response from the API?
It looks like you're using our partner API soap client. Our most current Reseller API is a REST API, and the entry point URL is:
https://www.idxhome.com/restServices/reseller/login
Documentation for the reseller API is not publicly posted at this time. Please email us at support#ihomefinder.com, and we would be happy to provide you the documentation.