I'm trying to create a Framework on top of Restlet and my question would be, is it possible to have a ServerResource to be "injected" from outside the org.restlet.Application code?
The standard way is to have a resource injected here:
public class FrameworkApplication extends Application {
private static final String ROOT_URI = "/";
/**
* Creates a root Restlet that will receive all incoming calls.
*/
#Override
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach(ROOT_URI, RootServerResource.class);
return router;
}
}
However since I am building a framework the use of FrameworkApplication is through including it as a dependency:
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>myframework</artifactId>
<version>0.0.1</version>
</dependency>
Going back to the question, I want to know if it is possible to have a ServerResource to be added in the Restlet routing like this:
public class PluggableResource extends ServerResource {
#Get("json")
public String represent() {
// stuff
return resp;
}
}
In the case of dependency injection, the solution was to do, SelfInjectingServerResource now can I make such a SelfAttachingServerResource?
I don't know what you exactly want to do but auto-discovering support of server resources isn't supported in Restlet. You need to implement by your own within a dedicated implementation of the class Application of Restlet. The method createInboundRoot would be responsible to scan the classpath to detect server resources. Moreover you need to add more metadata for server resources (with annotations for instance) to specify the attachement path.
However, the JAX-RS support provides this feature. It provides a set of annotations to make easy to identify server resources and provide metadata like attachement path, methods and exchanged media types for methods. Here is a sample of use: http://restlet.com/technical-resources/restlet-framework/guide/2.3/extensions/jaxrs. The classes for server resources need to be register by hand but you can go further. As a matter of fact, you can scan the classpath to detect classes having the annotation Path. See this link for the way to implement such ferature: Scanning Java annotations at runtime. In this case, they will be autodetected based on annotations. Is something can suit your needs?
Hope it helps.
Thierry
Related
I have recently started out with Spring and am unsure about how to approach this issue. I have a Spring boot program which makes calls to remote REST APIs. For example an AddressService class with getAddress(String user) method, which makes a HTTP call and returns a JSON response. I would like to set up Spring profiles for development purposes local, dev, uat, prod.
When the program is running with the local profile, I would like to "mock" these external API calls with an expected JSON response, so I can just test logic, but when it is run in any of the other profiles I would like to make the actual calls. How can I go about doing this? From what I read, there's many ways people approach this, using WireMock, RestTemplate, Mockito etc. I'm confused about which is the way to go.
Any advice would be greatly appreciated. Thanks.
WireMock,Mockit is for unittest, to mock the real request. Example here:
How do I mock a REST template exchange?
When you need a running implementation with a mock, i think the easiest way is that you have a interface
public interface AdressAdapter {
public List<Adress> getAddress(String name);
}
And two different implementations depending on the profile.
#Profile("local")
public class DummyAdress implements AdressAdapter{
#Override
public List<Adress> getAddress(String name) {
//Mock here something
return null;
}
}
! means NOT locale profile in this case.
#Profile("!local")
public class RealAdress implements AdressAdapter{
#Override
public List<Adress> getAddress(String name) {
//Make Restcall
return null;
}
}
What you could do is use different application.properties files depending on your profile. That way, you just change the url to a mock server for your local profile.
So what you have to do is :
Create another application.properties in your resources folder named : application-local.properties.
Change the url of the desired service.
Start your application with the VM option -Dspring.profiles.active=local.
Here is a link that describe well what you want to achieve.
For your mock server, you could use Wiremock, Mountebank, Postman,... that can be start separately and mock specific endpoints to return what you want.
I'm designing software with different components, that need to communicate with each other through a REST interface.
I've seen and implemented solutions, where the different components of the software (deployed on the same cluster) would communicate by declaring and injecting EJB beans. This way, it's really easy to standardize the communication by defining common interfaces and DTOs in a separate .jar dependency.
This level of comfort and standardization is what I'd like to achieve with RESTful services, between Java-based components of my software.
Imagine something like this:
Let's say, I have a REST Client (C) and a REST Server (S).
I'd like to be able to communicate between them, via a common interface, which is implemented in S and called by C. This common interface is in an API component (I).
It would mean that I would have an interface:
#RestController
#RequestMapping("/rest/user")
public class UserController {
#GetMapping("list")
ResponseEntity<List<UsersModel>> getUserList(OAuth2LoginAuthenticationToken token);
}
In C it could be used like:
public class Sg {
private final UserController userController;
...
public void method(OAuth2LoginAuthenticationToken token) {
...
userController.getUserList(token);
...
}
}
Lastly, in S:
public class UserControllerImpl implements UserController {
#Override
public ResponseEntity<List<UsersModel>> getUserList(OAuth2LoginAuthenticationToken token) {
...
}
}
The only configuration needed is to tell the client the context root (and host address) of the server, everything else is present in the common interface in the form of annotations.
Since not all components are necessarily Java-based, it is important for the REST resource to be callable in a typical REST-like way, so those Java remote service calling mechanics are out of consideration.
I was looking into JAX-RS, which seems promising, but is missing a couple of features that would be nice. For example, there isn't a common interface telling the client which endpoint on the server can the REST resource be found, neither are the method names, etc. AFAIK, on the client, you can only call the method representing the HTTP method of the request, which is a bummer.
Am I out of my mind with this spec? I'm not really experienced with REST services yet, so I don't really know if I'm speaking of something that is out of the REST services scope. Is there an already existing solution to the problem I face?
After more thorough research, I found that RESTeasy already has a solution for this.
You need to use the ProxyBuilder to create a proxy of your interface and that's it.
I am developing a web application using spring framework and google app engine. I am wondering if there is a design pattern or framework with the help of which I can develop features of my application as pluggable modules. For example I have identified 4 features of the application:
Oauth Login
User Profile Management
User Group creation
User File management
Now what I need is to develop all these features as independent modules, so that i can detach any of them dynamically and they are as loosely coupled as possible. They can have their own database implementation, their own set of technologies etc. Is there a design principle to implement modules in such a way.
You can take a look at MQ systems (such as RabbitMQ, ActiveMQ).
MQ system will work as intermediate layer, which provide you loosely coupling.
Communication between modules will be implemented as posting messages to queue and listening for posting.
Also, OSGI may help you. It gives you possibility to make your application as a set of pluggable modules, which might be loaded dynamically.
As per my experience, I suggest, Use MVC pattern. Use Servlet filttersfor 1.Oauth Login.
Create service/POJOs to implement and inject each other according to your requirement for
2.User Profile Management
3.User Group creation
4.User File management
If you know Spring AOP, use. So that you can achive more dynamic integration between implementations of points 2,3, and 4.
You should split the feature in two components: API and implementation. The first one contain interfaces, the second their implementations. You pass the interface to web app controller and inject implementation via Spring or any other Dependency Injection framework. For example
web-app, UserController which handles requests from client and delegate to your components
#Component
public class UserController {
private FileManager fileManager;
#Autowired
public UserController(FileManager fileManager) {
this.fileManager = fileManager;
}
#GET("/user/{userId}/file/{fileId}")
public File getUserFile(long userId, long fileId) {
fileManager.getUserFile(userId, fileId);
}
}
file-mgt-api where you define interfaces to decouple web-app from implementation
public interface FileManager {
File getUserFile(long userId, long fileId);
}
file-mgt-impl where all the details of how to get requested file
#Component
public class FileManagerImpl implements FileManager {
#Override
public File getUserFile(long userId, long fileId) {
// get file by id from DB
// verify that provided user is the file owner
// do other useful stuff
// return the file or throw exception if something wrong
}
}
Do the same for group, profile management and other features. After that you can easily replace implementation by replacing single jar file. Your web-app is completely decoupled and don't know anything about implementation details, it only depends on interfaces.
I've been going through this tutorial and they added a web service class instance to a hashSet, like this:
public class MessageApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public MessageApplication() {
singletons.add(new MessageRestService());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
I do not understand what the purpose of it is... I thought you could just access the web service with a URL
You made a class, this class is able to handle web requests. But this class has to be hosted somewhere. This means, this class has to be activated by a URL route. In this case you're using JBOSS.
In the first option of the tutorial, MKyong shows you how to configure RESTEasy Bootstrap (a bootstrap to load references) to map the URL with your class. This is done in web.xml and configures some kind of scanner that will map a certain URL with your class.
The second option is not using RESTEasy Bootstrap and you have to add your class to a collection of long living objects in your application manually. This is done defining the Application (MessageAplication) and defining it in the web.xml.
Yes, you can access the webservice via a URL, but the server needs to know what to do with calls to a certain URL.
Yours is one way (the bootstrap version) of telling the application server where to look for JAX-RS resources: http://www.mastertheboss.com/resteasy/resteasy-tutorial (Step #4)
There is a (newer) alternative, depending on which server and RESTeasy-version you use, which relies on autoscanning for certain annotations. For RESTeasy on JBoss, it's described at the bottom of the tutorial-page I linked.
I am trying to create a dynamic proxy that would wrap an EJB around a web service because the application server does not support creating an EJB based web service without a proprietary router project generation.
My thought was to create a dynamic proxy, and some how just start it using an InitServlet. Right now I am kind of stuck on figuring out how to set the annotations dynamically so that I won't get the following error.
class $Proxy0 has neither #WebSerivce nor #WebServiceProvider annotation
at com.sun.xml.internal.ws.server.EndpointFactory.verifyImplementorClass(EndpointFactory.java:277)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.getPrimaryWsdl(EndpointImpl.java:273)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.createEndpoint(EndpointImpl.java:213)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(EndpointImpl.java:143)
Recently I have had the same problem. It seems that most people say is not possible. See http://softwarecarnival.blogspot.be/2009/02/java-annotations-and-proxies.html
If the interface that you have is:
interface XXXInterface{
Result doStuff1(String param1)
}
then a workaround is to create a delegator to the proxy that will also implement the web service.
#WebService
public class WebServiceDelegateToXXXServer implements XXXInterface{
public WebServiceDelegateToXXXServer(XXXInterface actualImplementor){
this.actualImplementor = actualImplementor;
}
public Result doStuff1(String param1){
return actualImplementor.doStuff1(param1);
}
}
Then you will publish
XXXInterface proxy = createProxyAsXXXInterface();
Endpoint.publish(url, new WebServiceDelegateToXXXServer(proxy));