Passing Objects to a Web Service's method - web-services

I have recently started working on (Java)Web Services.
I have certain web methods that accept different arguments - primitives,Maps,HttpServletRequest,FlowJob(Spring) etc.
I got numerous issues while attempting this - from a failed web service deployment saying 'interfaces not supported by JAX-WS' to runtime exceptions 'java.lang.Object cannot be cast to org.w3c.dom.Element' !
I have not put the steps deliberately;all I need to know is that is it possible to pass the above arguments to a Java Web Service method? In short,is something like this possible :
#WebService(serviceName = "WS")
public class WS {
#WebMethod
public Object processJob(MapargsMap){
}
#WebMethod
public String processJob(SomeCustomObject object){
}
}
}
Are there any work-arounds to make JAXB marshal and unmarshal custom objects,Maps etc.?If yes,what are they?
Thanks & regards !

Related

How to mock objects in Golang 1.19 for testing purposes?

I'm writing a client built on top of a mongo.Client from the "mongo" package. Because of the nature of mongo client which requires a live database connection, I've decided to try the mocking approach, that is, to store an interface with a set of methods (which also return the interfaces) I would use on the mongo client.
The issue is that the return type of some mongo functions doesn't implement my interfaces for a reason which I do not understand.
For example, mongo.Collection doesn't implement my ICollection interface, however, the mongo.SingleResult does implement the ISingleResult interface:
type ICollection interface {
FindOne(context.Context, interface{}, ...*options.FindOneOptions) ISingleResult
}
type ISingleResult interface {
Decode(v interface{}) error
}
The issue is gone if I change the return type from ISingleResult to *mongo.SingleResult, but this is not what I want, because I could not control the *mongo.SingleResult logic and track its calls as I could do with its mock.
Please help me to fix that logic or provide another testing approach which is more common if my is wrong.

CDI Inject in Stateless Session Beans requests

Currently we have an elaborate POJO object structure for handling a webservice request, called a 'processor'.
Remote and Local EJB's and PersistenceContext called during serving this request are initialized in the statless bean and handed to this 'processors' constructor which is re-created during each webservice request.
If I do not want to revert to JNDI lookups deep down in my 'processor' I keep on dragging around all these EJB's through my code.
Enter CDI. I would like to be able to inject these EJB's whenever I need them in this 'processor'.
However, I also noticed this means that the current 'processor' has to become a CDI bean itselve: so, using the #Inject in the Stateless Session Bean that implements the webservice.
When I do this the entiry lifecycle of the processor becomes bound to the bean and not to the request its serving.
Suddenly I have to take into consideration that I should not retain state (other than the injected objects) in the processor, since this state will be shared between multiple webservice invocations. As a programmer, this is not making my life more easy.
So: how should I go about doing this? I've read about the scoping but I'm not sure how / if this would be helping me.
Example, stateless bean:
#Stateless
#WebService
public class ExampleBean {
#Inject
Processor requestScopedInstance;
int beanDependentScopeCounter;
public String sayHello() {
System.out.println( "bean object id: " + this.toString() );
return requestScopedInstance.sayHello(beanDependentScopeCounter++);
}
}
interface:
public interface Processor {
String sayHello(int beanScopedCounter);
}
Implementation:
public class ProcessorImpl implements Processor {
private int requestScopedCounter = 0;
#Override
public String sayHello(int beanScopedCounter) {
return "test, requestScoped: " + requestScopedCounter++ + ", beansScoped: " + beanScopedCounter;
}
}
When I do this the entiry lifecycle of the processor becomes bound to the bean and not to the request its serving that is not correct. That is only the case if you don't use #ApplicationScoped, #SessionScoped, #RequestScoped.
So:
Annotate your processor with #RequestScoped.
You don't need to hand over the EJBs, you can just inject them, where needed.
Use #PostConstruct annotated methods for constructor-code which uses injected objects.
stateless POJOs can be annotated #ApplicationScoped, not stateless POJOs can stay dependent-scoped which is default.
That is made possible because proxies are injected, not actual beans. Using these proxies CDI makes sure that the correct scope is used for your particular calls.

How do I implement functions in a Bond services definition?

Looking at the Bond Comm documentation, it wasn't clear to me how the functions I define for services are connected to specific functions in my code.
Does it look for a function with the same signature in the project and assign it to the endpoint? Is there some underlying settings file I am missing?
NB: Bond Comm is deprecated. It isn't supported any more, and will be removed from Bond in an upcoming release. Bond-over-gRPC is its replacement.
When using either Bond-over-gRPC or Bond Comm, the generated server-side code is an abstract class with an abstract method for each method in the service definition. To provide your logic for these methods, you inherit from the generated base and provide implementations for all the service methods. Then, typically in your main function, you create a Server (for Bond-over-gRPC) or a Listener (for Bond Comm) and register an instance of the implementation class. This sets up the routing for IDL service method to your implementation code.
From the Bond-over-gRPC C# documentation:
Given a service definition like the following:
service Example
{
ExampleResponse ExampleMethod(ExampleRequest);
}
gbc will generate C# classes for gRPC with the --grpc flag:
gbc c# --grpc example.bond
...
To build the service functionality, simply write a concrete service
implementation by subclassing the server base and supplying the
business logic:
public class ExampleServiceImpl : Example.ExampleBase {
public override async Task<IMessage<ExampleResponse>>
ExampleMethod(
IMessage<ExampleRequest> param,
ServerCallContext context)
{
ExampleRequest request = param.Payload.Deserialize();
var response = new ExampleResponse();
// Service business logic goes here
return Message.From(response);
}
}
This service implementation is hooked up to a gRPC server as follows:
var server = new Grpc.Core.Server {
Services = { Example.BindService(new ExampleServiceImpl()) },
Ports = { new Grpc.Core.ServerPort(ExampleHost, ExamplePort, Grpc.Core.ServerCredentials.Insecure) } };
server.Start();
At this point the server is ready to receive requests and route them to the
service implementation.
There are more examples as well:
a standalone C# project
a C# ping/pong example
a C++ "Hello World" example
a C++ ping/pong example
It's worth pointing out that (Bond-over-) gRPC and Bond Comm are neither SOAP nor REST. The question was tagged with web-service, and sometimes people mean SOAP/REST when they talk about web services. I think of both gRPC and Bond Comm as custom binary protocols over TCP, although gRPC is run atop HTTP/2.

Mock an Eureka Feign Client for Unittesting

i am using spring cloud's eureka and feign to communicate between some services (lets say A and B). Now id like to unittest my service layer of a single service (A). The problem is, that this service (A) is using a feign client to request some information of the other service (B).
Running the unittests without any special configuration throws the following exception: java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: service-b => but i do not want any server to run.
My question is: Is there a way to mock the feign client, so i can unittest my service (A) without running an eureka instance and service (B)?
Edit:
I ended up creating a stub for the feign client. The stub is marked as a primary component to force spring instantiating the stub within my tests.
This is the solution i came up with.
//the feign client
#FeignClient("user")
public interface UserClient {
UserEntity getUser();
}
//the implementation i use for the tests
#Component
#Primary //mark as primary implementation
public class UserClientTestImpl implements UserClient {
#Override public UserEntity getUser() {
return someKindOfUser;
}
}
The question is ... do you even need to mock? I often see that people mention "mock" as the first solution to anything that "should not be part of the unit test". Mocking is a technique, not the solution to everything. (see here).
If you are still at the early stages of your code, just refactor and use something else instead of depending on the concrete instance of the Feign Client. You might use an interface, an abstract class, a trait or whatever you want. Don't depend on the object itself, otherwise you have to "mock it".
public interface IWebClient {
public String get(...);
public String post(...);
}
To the question: but I will have other code that will do exactly the same (except that it will be on the concrete instance of Feign), what do I do then?
Well, you can write a functional test and call an instance of a web server that you can setup locally - or use Wiremock, as mentioned by Marcin Grzejszczak in one of the answers.
public class FeignClientWrapper implements IWebClient {
private feign = something
public String get() {
feign.get( ... )
}
public String post() {
feign.post( ... )
}
}
Unit tests are used to test algorithms, if/else, loops: how units work. Don't write code to make mocks fit - it must be the other way around: your code should have less dependencies, and you should mock only when you need to verify the behavior (otherwise you can use a stub or a fake object): do you need to verify the behavior? Do you need to test that a particular method gets called in your code? Or that a particular method gets called with X, Y, and Z for 3 times in a row? Well, then yes, mocking is ok.
Otherwise, use a fake object: what you want is to test just the call/response and maybe the status code. All you probably want is to test how your code reacts to different outputs (e.g., the field "error" is present or not in a JSON response), different status codes (assuming that the Client documentation is right: 200 OK when GET, 201 when POST, etc).
Mocking a feign client is really useful in microservice component tests. You want to test one microservice without having to start all the other microservices.
If you're using Spring (and it looks like you are), the #MockBean annotation together with a bit of Mockito code will do the job.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment =
SpringBootTest.WebEnvironment.DEFINED_PORT)
public class TestYourComponent {
#Configuration
#Import({YourConfiguration.class})
public static class TestConfiguration {
}
#MockBean
private UserClient userClient;
#Test
public void someTest()
{
//...
mockSomeBehavior();
//...
}
private void mockSomeBehavior() {
Mockito.doReturn(someKindOfUser).when(userClient).getUser();
}
}
If you need to use a mock you can use Wiremock to stub the response for a given request - http://wiremock.org/stubbing.html. That way you will do integration tests with real HTTP requests sent. For unit testing the answer from #Markon is very good.

Exposing existing API as a Web service

I am currently working on a task to expose an API as a Web service. The idea here is to package the existing business logic in JAR files into a WAR file and expose the WAR file as a Web service that would return a free-form XML string. When we expose an existing API as a Web service, is it sufficient that we make available an XSD & WSDL file of the returned XML string data? Is that the convention or the standard practice?
It depends on whether or not you are using SOAP or REST. SOAP is more restrictive; as a result, it's more expected that you'll have a WSDL file to generate the classes that interface with the API.
On the other hand, if you are using REST, just exposing a RESTful URI would be considered enough to meet the constraint of a RESTful web service having a uniform interface.
REST tends to be gaining more ground over SOAP since it is a permissive architectural style. I would prefer this method, and I would recommend this method if you're new to developing web services.
Depending on what language you are using, I'm assuming Java, you can use Restlets or Spring 3.0's REST framework to help you build a RESTful web service. These tools really make that job a lot easier and help you conform to the 6 Constraints of a RESTful Web Service and meet the 4 Key Goals.
UPDATE:
Assuming you already have existing, object-oriented code, and assuming you want to expose that code as a REST API, using Spring 3.0 MVC, create a Controller subclass that will wrap around your existing package:
Example GET:
Resource: Javadocs for Jackson's ObjectMapper POJO/JSON Marshaller
// this is the wrapper around your existing Java packages.
#Controller
public class UserController {
protected static final DATA_TYPE = "json";
// In REST, GET method is used to retrieve data with no side effects,
// meaning that no changes are made to the data on the server.
#RequestMapping(value="/users/{username}", method=RequestMethod.GET)
public void getUserData(#PathVariable("username") String userName, Model model) {
// this is your existing class
UserDataService userDataService = new UserDataService();
// assume you have a class User, and getUserDetails gives you that POJO object.
User user = userDataService.getUserDetails(username);
// marshal the User object to JSON, using Jackson, and write as output in response
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getWriter(), user);
}
}
// assume you have an existing POJO class called User
class User implements Serializable {
String username;
String age;
String birthday;
String mood;
String getMood() { return this.mood; }
String getBirthday() { return this.birthday; }
String getAge() { return this.age; }
String getUsername() { return this.username; }
String setMood(String mood) { this.mood = mood; }
String setBirthday(String birthday) { this.birthday = birthday; }
String setAge(String age) { this.age = age; }
String setUsername(String username) { this.username = username; }
}
Request:
http://api.example.com:8080/users/jmort253/
Response:
{
"username":"jmort253",
"mood":"good",
"age":"not too old and not too young",
"birthday","Jan 1, 1900"
}
XML instead of JSON:
The main difference between returning XML and returning JSON is in the marshaller used. Using javax.xml.bind.annotations, you can place annotations on the POJO class so the marshaller can convert it to XML, freeing you up from the details of having to manually code XML by hand:
Using javax.xml.bind.annotations to convert Java Objects to XML and XSD. This resource also explains how to generate the XML Schema, if you deem that as a requirement to your REST Web service.
#XmlRootElement
class User implements Serializable {
String username;
String age;
String birthday;
String mood;
String getMood() { return this.mood; }
String getBirthday() { return this.birthday; }
String getAge() { return this.age; }
String getUsername() { return this.username; }
String setMood(String mood) { this.mood = mood; }
String setBirthday(String birthday) { this.birthday = birthday; }
String setAge(String age) { this.age = age; }
String setUsername(String username) { this.username = username; }
}
Instead of using the Jackson API's ObjectMapper class to marshal the POJO class to JSON, use the javax.xml.bind.annotations package in place of ObjectMapper:
JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();
// pretty print XML
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(user, System.out);
Aside from the other resources, this article has a few examples that use JAXB to deserialize an ArrayList of POJO objects to XML.
My final suggestion when working on the REST Web service wrappers is to set your logging levels to "ALL" or "DEBUG". I find that this helps me more easily determine the root cause of any problems I face when setting up a Web service. The libraries themselves will output helpful debug messages to help you resolve configuration issues, such as missing dependencies, missing annotations, and other issues that you'll likely encounter when dealing with the conversion to XML/JSON process or in setting up Spring 3.0.
Once you're uniform interfaces are setup and you can make GET requests and receive responses, you can then set the logging levels back to the previous INFO or WARN levels.
First of all, I would hesitate before exposing an existing API as a web service on a one-for-one basis. Was the existing API written to be accessed over a network? If not, then it was probably not designed with networking constraints in mind.
It may include method calls which will involve larger numbers of small operations - the kind that cost nothing when used within a single process. Over a network, each call has an associated latency that is much larger than the overhead of caling a method within the same process.
Instead, I would design a service to meet the functional requirements of the API. The service would likely be designed to have a smaller number of operations which perform more work per operation, thereby minimizing the overhead associated with network traffic. The service would likely be implemented by calling on the API (assuming it is written to handle multi-threaded environments like a service).
In terms of WSDL, the toolkit you are using may very well construct a WSDL for you. I know that WCF in .NET does that, and I have done the same using IBM Rational Web Developer, so I know that the Java world can do the same.
Otherwise, it's not actually that hard to hand-write a WSDL and corresponding schema. In either case, they do need to be provided so that your clients can consume the service.
There's nothing wrong with using REST for this if your API can be cleanly expressed as a set of operations on resources. In this case, yes, provide the schema to make it easier for your clients to process the XML. I would beware of forcing your API to fit the REST model if it is not cleanly expressible as operations on resources.