Annotation endpoint Location for JAX-WS - spring

does exist a specific annotation to define the address of the endpoint.
In fact, I want to remove the attribute address in the SPring file and move the annotation directly in the impl. class.
Current:
jaxws:endpoint id="dataManagerEndPoint" implementor="#dataManagerService" address="/datamanager/v1.0"
#WebService
public interface DataManagerService
I would like to change to (if possible) ...
jaxws:endpoint id="dataManagerEndPoint" implementor="#dataManagerService"
#WebService
#EndPointAddress ("/datamanager/v1.0")
public interface DataManagerService
Many thanks, in advance,
Christophe P.

#WebService(portName = "PortTypeName", serviceName = "ServiceName", targetNamespace = "http://www.namespace.com", wsdlLocation = "META-INF/wsdlname.wsdl", endpointInterface = "com.package.service.PortTypeName")

Related

#ConstructorBinding data class Properties with numbers as names

i'm adding property validation to an existing big project. It has hundrets of webservices and there are some that have simple numbers as names.
Now im trying to write a data class using #Validated, #ConstructorBinding and #ConfigurationProperties.
So imagine a property
dummy.941=http:...
The name of the variable would need to be 941 now, as far as i can tell, but kotlin/java dont allow variable names starting with numbers.
#Validated
#ConstructorBinding
#ConfigurationProperties(value = "dummy", ignoreUnknownFields = false)
data class DummyProperties(
val abc: Abc = Abc(), ....
val 941: Ws941: Ws941()
)
Is there any workaround, some annotation, that says which property is meant? It is not possible to change the name of the property, since the same property database is in use different working systems and people told me thats off the table.
Thanks for any help!
EDIT:
I found a way, spring offers a #Name annotation (org.springframework.boot.context.properties.bind)
#Valid
#Name(value = "703")
val s703: S703 = S703(),
Works like a charm:)
Some time ago, I had a similar issue. You can solve it, at least for Java, by using a custom setter. I have no idea about Kotlin, but I assume it works in the same way for Spring Kotlin.
#ConfigurationProperties(value = "dummy", ignoreUnknownFields = false)
public class DummyProperties {
private Ws941 _941;
public void set941(Ws941 _941) {
this._941 = _941;
}
public Ws941 get941() {
return this._941;
}
}
Spring can map using the setter, so the variable can have a different name.

#RestController over interface + spring

I accidentally found this technique of using RestController annotation.
(I saw this not on the internet, but in one of the examples that I was shown. I couldn't find it on the internet)
#RestController
#RequestMapping("api/user/point")
public interface ExampleRestController {
#PostMapping("{key}" )
#Operation(summary = "Manage...",
description = "Allow user ...")
public HttpStatus changePoints(
#PathVariable
#NotBlank
#Parameter(description = "Id user") String key,
#RequestParam("point")
#Min(0) #Parameter(description = "count something..", required = true) Long point,
#RequestParam("type")
#Parameter(description = "Type of...", required = true) TypeOperation type
);
}
What is this technique, who knows ?
I've seen the Rest Api just like this. Can Spring also dynamically create an endpoint method in the RestController, as it does when executing ...extend CrudRepository ? And how does AOP work in this case ? After all, in order for the bean to be configured, we need to put the annotation above the class (like how it is done at the service level), if you put it above the interface, the full automatic configuration of the bean is not guaranteed
It is spring-interface-driven-controllers.
This is new feature of Spring MVC. ( starting with Spring 5.1)

Passing of list of type Baseclass between Webservices involving generics and conversion of polymorphic types

I have two REST services using Spring Boot running on two different servers. I am using REST Template for this communication.
There are some models that are shared by these two services. All these models are of type 'IDataToTransferred' .
'IDataToTransferred' is a marker Interface implemented by various Model Beans.
I need to write a common logic for passing a list of these models between these REST services.
Hence I wrote a logic which uses parameters
List<? extends IDataToTransferred> from Sender service to Receiver Service.
Update: With Some Code
IDataToTransferred.java is a marker Interface
DataToBeSent.java
DataToBeSent Implements IDataToTransferred{
//Simple Pojo
}
SenderService.java
sendData(List<? extends IDataToTransferred> uploadDataObjectList){
//Some Code with REST Template
//restTemplate.postForEntity
}
IDataToTransferred Interface is shared between communicating webservices.
DataToBeReceived.java
DataToBeReceived Implements IDataToTransferred{
//Simple Pojo
}
ReceiverService.java
receiveData(List<? extends IDataToTransferred> uploadDataObjectList){
//Some Code to convert uploadDataObjectList to DataToBeReceived
}
Note In REST service I was always getting 415 error. Unsupported Media type. when I use the same List<? extends IDataToTransferred> on Receiver.
When I changed this to List<? super IDataToTransferred> on Receiver side, now it works, I am guessing because of Producer extends Consumer super rules.
But the problem is that now I can't typecast to the IDataToTransferred type on Receiver Side. Inside the list I am getting all linkedHashmap, the json got converted to linked HashMap between these services.
How can I get DataToBeReceived class object in ReceiverService?
For simplicity sake I have removed Controllers. Assume that they have the same signature as the services.
If I had known better terms to search, I would have found answer before Posting. But alas.
In any case I found the answer in stackoverflow page here together with a this blog ofcourse.
The examples are with abstract classes. I have used with interfaces.
As mentioned in the link. I Introduced below annotation in the marker interface IDataToTransferred:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
#Type(value = DataToBeSent.class, name = "datatransfer")})
The property type is introduced in the bean DataToBeSent as a property. This type param is used as information for conversion into implementing type from interface type. One can use a different variable than one named "type". In JsonSubTypes annotation , we mention the classes that are implementing this interface.
DataToBeSent Implements IDataToTransferred{
//Simple Pojo
// Some Properties with getter and setter
String type = "datatransfer";
//with getter and setter
}
The same exercise needs to be implemented on the Receiver Side also. Hence, we will have annotation as below:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
#Type(value = DataToBeReceived.class, name = "datatransfer")})
Here, we have DataToBeReceived class as implementing the IDataToTransferred interface. Ofcourse you need to add type as property to DataToBeReceived class also as below:
DataToBeReceived Implements IDataToTransferred{
//Simple Pojo
// Some Properties with getter and setter
String type = "datatransfer";
//with getter and setter
}
Hope this helps.

Custom nested actuator endpoint

Using Spring Boot 1.0, I was able to customize the actuator endpoints as follows...
endpoints.beans.id=foo/springbeans
This would expose the spring beans endpoint at /foo/springbeans. However, in the latest Spring Boot this is not possible due to the following code in the AbstractEndpoint...
#NotNull
#Pattern(regexp = "\\w+", message = "ID must only contains letters, numbers and '_'")
private String id;
I tried using the underscore, but that just exposes the endpoint at /foo_springbeans. This lead me to try to add a view controller so I could at least redirect or forward to the default endpoint, but I couldn't find an easy way to do that either. How can I configure the endpoint or a redirect?
After opening an issue with Spring Boot and being told to simply move the entire management context as suggested by Rafal, I was able to achieve what I was looking for, albeit with more code than I'd like. I created a custom MvcEndpoint as follows...
#Named
public class MyCustomHealthCheck extends EndpointMvcAdapter {
private HealthEndpoint delegate;
#Inject
public MyCustomHealthCheck(HealthEndpoint delegate) {
super(delegate);
this.delegate = delegate;
}
#ResponseBody
#RequestMapping(value = "/springbeans", method = GET)
public Health foo() {
return delegate.invoke();
}
}
The code above creates the /springbeans path underwhatever path the HealthEndpoint is mapped to, which is fine enough for my usecase. If I wanted it mapped to an entirely separate path, I would have needed to create a dummy endpoint and stick this MvcEndpoint under that.
For Spring 1.x Following property should help you:
endpoints.beans.path: /foo/springbeans
You can use it with any standard endpoint and if you want to use it with custom endpoint that extends AbstractEndpoint then you need additional annotation:
#ConfigurationProperties(prefix = "endpoints.customEndpoint")
and then use property:
endpoints.customEndpoint.path: /custom/endpoint

Filtering OSGi services using SlingScriptHelper#getService() method

I want to instantiate a service object in my jsp using sling taglib. In normal scenario where the service class is being implemented by only 1 class, its pretty simple:-
RegistrationService registrationService = sling.getService(RegistrationService.class);
But if the service class has more than 1 implementation classes, then how can we make sure to instantiate object for a particular class.
My java class are like:-
1. Interface: RegistrationService
2. Implementation Class 1:-
#Properties({#Property(name = "datasource", value = "SBWS"})
#Service
public class RegistrationServiceImpl implements RegistrationService{
}
3. Implementation Class 2:-
#Properties({#Property(name = "datasource", value = "SOLR"})
#Service
public class RegistrationServiceImpl implements RegistrationService{
}
How can I make sure that using
RegistrationService registrationService = sling.getService(RegistrationService.class);
in jsp will instantiate service for let say implementation class 1
Use SlingScriptHelper#getServices(...) method, which allows to specify a filter:
RegistrationService[] services = sling.getServices(RegistrationService.class, "(datasource=SBWS)");
if (services.length > 0) {
// services[0] contains your service
}
Getting OSGi service and filtering it via properties is quite low-level stuff, consider moving it from JSP to a Java class.

Resources