Expose SOAP Endpoint With cxf-spring-boot-starter-jaxws - spring-boot

I am trying to expose cxf web services from my Spring Boot Application. I am trying to use the cxf-spring-boot-starter-jaxws v3.2.6. The documentation for the starter is a bit out of date. The examples shows the following for exposing and endpoint.
#Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, new HelloPortImpl());
endpoint.publish("/Hello");
return endpoint;
}
But now the EndpointImpl takes 3 arguments and I am trying to understand how to construct one.

My mistake, I was using the EndpointImpl from the wrong package. I was trying to use org.apache.cxf.endpoint.EndpointImpl and not org.apacke.cxf.jaxws.EndpointImpl

Related

Override URL and Authentication configuration of Spring Cloud Feign client

I am trying to leverage Spring Cloud Feign client for declaring rest endpoints(third-party-endpoints) which will be called based on the request that my controller receives.
I have declared a feign client interface like:
#FeignClient(name = "my-client", url = "https://abc.xyz.com", configuration = MyClientConfiguration.class)
public interface MyFeignClient{
}
MyClientConfiguration is an unannotated feign configuration class just exposing BasicAuthRequestInterceptor bean preconfigured with some credential.
public class MyClientConfiguration {
#Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
return new BasicAuthRequestInterceptor("USERID","PWD");
}
}
So, what I have right now is a preconfigured feign client.
I am not sure how do I deal with the requirement that asks for being able to define/override the feign configuration with the url and credentials received in the body of different POST request.
So its not about overriding the feign configuration via properties file(like other somewhat similar SO questions), but instead being able to configure the feign client on the fly based on the url and credentials received in the body of the incoming requests.
I am aware of ways to do it with WebClient and looking for something similar to what WebClient provides via its uri and headers methods. Webclient allows us to override the webClient bean configuration with different uri and different auth credentials,
webClient
.put()
.uri("base-uri", uriBuilder -> uriBuilder.path("/rest").path("/api").path("/2").path("/issue").path("/" + id).build())
.headers(httpHeaders -> {
httpHeaders.setBasicAuth("decrypted-username", "decrypted-pwd");
})
Does Spring Cloud Feign provide any such facility where it is possible to have a generic configuration yet allowing to override those configurations at runtime?
EDIT 1 : START
The closest I got to is implementing via the feign's builder pattern :
MyFeignClient myFeignClient = Feign.builder()
.contract(new SpringMvcContract())
.requestInterceptor(new BasicAuthRequestInterceptor("decrypted-username", "decrypted-pwd")
.target(MyFeignClient.class, myRequestDTO.getBaseUrl());
I was challenged with an exception because I didn't specify which Contract to use. It was using the Default Contract.I then changed to SpringMvcContract as the annotation that I am using are the Spring MVC ones and not feign's default.
Getting DecodeException as of now. Trying to fix it. Will post update when done.
EDIT 1 : END
EDIT 2 : START
I was finally able to get this working. I figured out that the feign-gson does a great job at deserialization with minimal configuration.
My final feign configuration with the Decoder in place looks like :
MyFeignClient myFeignClient = Feign.builder()
.contract(new SpringMvcContract())
.decoder(new GsonDecoder())
.requestInterceptor(new BasicAuthRequestInterceptor("decrypted-username", "decrypted-pwd")
.target(MyFeignClient.class, myRequestDTO.getBaseUrl());
EDIT 2 : END

OAuth2 / OpenID Connect configuration in Spring Boot and OpenAPI

I am securing my application with OpenID Connect and Keycloak.
My API documentation is OpenAPI 3 which I generate from code.
#Bean
public OpenAPI customOpenAPI() {
OAuthFlows flows = new OAuthFlows();
OAuthFlow flow = new OAuthFlow();
String authUrl = authServerUrl + "/realms/" + realm + "/protocol/openid-connect/auth";
flow.setAuthorizationUrl(authUrl);
Scopes scopes = new Scopes();
flow.setScopes(scopes);
flows = flows.implicit(flow);
return new OpenAPI()
.components(new Components().addSecuritySchemes("keycloak",
new SecurityScheme().type(SecurityScheme.Type.OAUTH2).in(SecurityScheme.In.HEADER).flows(flows)))
.info(new Info().title(appName)
.version(appVersion))
.addSecurityItem(new SecurityRequirement().addList("keycloak",
Arrays.asList("read", "write")));
}
This works fine as I can authenticate via Keycloak's implicit flow. Now I want to secure only some endpoints and not all in my API.
I tried to annotate the desired endpoint with
#SecurityRequirement(name = "keycloak")
This seems to work. When I look in the JSON api-docs of my Swagger UI HTML, I can see that this entity is added to the endpoint configuration.
The problem seems to be that it is also placed as a global statement in the docs, so it is used for every endpoint.
QUESTION:
Is there a way to define the security scheme as non-global so I can place it to specific endpoints?
I could not find much documentation on configuring OpenAPI 3 by code. I've seen a way to add it via Annotation to the main class of the object via #OpenAPIDefinition( but I could not find a documentation for it and I did not figure out how to define the openid connect specifics within this annotation.

How to inject Feign Client with out using Spring Boot and call a REST Endpoint

I have two Java processes - which get spawned from the same Jar using different run configurations
Process A - Client UI component , Developed Using Spring bean xml based approach. No Spring Boot is there.
Process B - A new Springboot Based component , hosts REST End points.
Now from Process A , on various button click how can I call the REST end points on Process B using Feign Client.
Note - Since Process A is Spring XML based , right at the moment we can not convert that to Spring boot. Hence #EnableFeignClients can not be used to initialise the Feign Clients
So Two questions
1) If the above is possible how to do it ?
2) Till Process A is moved to Spring boot - is Feign still an easier option than spring REST template ?
Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSockets and you can easily use feign without spring boot. And Yes, feign still better option to use because Feign Simplify the HTTP API Clients using declarative way as Spring REST does.
1) Define http methods and endpoints in interface.
#Headers({"Content-Type: application/json"})
public interface NotificationClient {
#RequestLine("POST")
String notify(URI uri, #HeaderMap Map<String, Object> headers, NotificationBody body);
}
2) Create Feign client using Feign.builder() method.
Feign.builder()
.encoder(new JacksonEncoder())
.decoder(customDecoder())
.target(Target.EmptyTarget.create(NotificationClient.class));
There are various decoders available in feign to simplify your tasks.
You are able to just initialise Feign in any code (without spring) just like in the readme example:
public static void main(String... args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
...
}
Please take a look at the getting started guide: feign on github

Spring cloud gateway cannot find Fluent Java Routes API

I am trying my hands on Spring-cloud-gateway. While going through the documentation I found that we can configure routes not only in yml/ properties file, but also using Fluent Routes API. Here is the snippet from the documentation.
#Bean
public RouteLocator customRouteLocator(ThrottleGatewayFilterFactory throttle) {
return Routes.locator()
.route("test")
.predicate(host("**.abc.org").and(path("/image/png")))
.addResponseHeader("X-TestHeader", "foobar")
.uri("http://httpbin.org:80")
.route("test2")
.predicate(path("/image/webp"))
.add(addResponseHeader("X-AnotherHeader", "baz"))
.uri("http://httpbin.org:80")
.route("test3")
.order(-1)
.predicate(host("**.throttle.org").and(path("/get")))
.add(throttle.apply(tuple().of("capacity", 1,
"refillTokens", 1,
"refillPeriod", 10,
"refillUnit", "SECONDS")))
.uri("http://httpbin.org:80")
.build();
}
But I am not able to find this class Routes. Not sure If I have missed anything. I am using spring boot 2.0.0.M7 and I have spring-cloud-starter-gateway depependecy included.
Any idea ?
Routes is no longer available. Add a RouteLocatorBuilder parameter to customRouteLocator. I'll fix the docs.

How to manually call a microservice from a JHIPSTER gateway repository or service

I'm new to Jhipster, and wondering if it's possible to manually call a microservices from the gateway code using a RestTemplate or something else.
My first idea was to call the gateway itself... but I'm not sure it's a good idea.
My second idea was to try and call the service by it's URL. My concern is that I don't want to hardcode the port of a given node. Instead, i want to use proper loadbalancing.
I've read this article https://dzone.com/articles/spring-cloud-rest-client-with-netflix-ribbon-basic, but the injection failed.
I've read somewhere else that you now need to manually add the bean declaration
#LoadBalanced
#Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
But now I'm struggling with the actual URI : what I am supposed to put as the root? (xxxxx)
final HcpVersionedhcp hcpVersionedhcp =
restTemplate.exchange("http://xxxxx/api/user-data/byLogin/", UserData.class);
The only configuration I have in my gateway application.yml is
ribbon:
eureka:
enabled: true
The "xxxxx" has to be replaced with your services name. If your service is "foo", you should write http://foo/api/user....
If you are using JWT as authentication, you need to auth using a user a in JHipster, or to pass the JWT token from request when possible. However the is no best practice for JWT auth, so I would suggest to go the JHipster UAA way.
In a few words, you have one more service responsible for authentication and authorization. To access your service from another service, you can use #AuthorizedFeignClient on interfaces, similar to JPA.
So you define:
#AuthorizedFeignClient(name = "xxxx")
interface XxxClient {
#RequestMapping(value = "/api/some-entities/{id}")
SomeEntity getSomeEntityById(Long #Path("id") id);
}
And inject it in any spring service / rest-controller like this:
#Inject
private XxxClient xxxClient;
//...
public void someAction() {
//...
xxxClient.getEntityById(id);
//..
}
Which internally implement client authorization flows ...

Resources