I have two web servers A and C. Because of rules, policies etc A cannot communicate directly with C' (Crequires requests to have special security headers andA` does not support this)
I want to create a "proxy" called B in Java, to facilitate communication between A and B but I having trouble with it conceptually.
When you create a proxy, don't you have to change the hard coded URLs on all your services to now travel through the proxy? And then I suppose you must pass your destination as a query parameter somehow, for example
http://proxy.com/?destination=mydestination.com
Is this how a proxy would work?
(I have found a few similar questions but they do not resolve the fundamental question I am having i.e. How packets reaches Destination throgh proxy servers?)
Don't write your own proxy from scratch that will be a redo, there are a plenty of proxy implementations out there
Spring framework
Spring Boot implementation for (Netflex/Zuul) https://github.com/Netflix/zuul / https://spring.io/guides/gs/routing-and-filtering/
Standard Servlet
https://github.com/mitre/HTTP-Proxy-Servlet
in case if you are intrested in how you can build up your own proxy , here is a simple example using spring framework (Servlet implementation is not that far from spring implementation)
#RestController
public class ProxyController {
/**
* request handler for all the requests on the registered context intended to be proxied
*
* #param request
* #return
*/
#RequestMapping("/**")
public String defaultGateway(HttpServletRequest request) {
// edit the original request headers,body etc
String originalPath = request.getRequestURI();
// then fire another HTTP request using the same URI
return "ProxiedResult"; // return back the result you get from
}
}
the example above is a start point on how to implements HTTP proxy or how it is working there are many things to cover which is droped off like security for instance
Related
I am writing an OSGI service component in AEM.
I want to fetch current domain name in the activate method of the service component.
Currently, I'm writing a construct method, to get request from referring class/service/model/servlet to initialize the 'request' class object and using this request object to get the server name
private SlingHttpServletRequest request;
private String domainName;
#Override
public void construct(final SlingHttpServletRequest request) {
this.request = request;
}
#Override
public void setDomainName(){
this.domainName = request.getServerName();
}
And this.domainName is used in multiple service method implementations.
So, I have to call 2 extra service method,
Construct - to initialize global request object
setDomainName - to initialize domainName global object to be used across all the other service methods
Is there anyway to get domainName in activate method, so that i do not have to call the above two methods in order to use the service.
Note:- I cannot create an OSGI config for domain name, as this domain name is already being used as key property to identify the OSGI config of a given factory
Since AEM publish servers might be used for several domains, there is no way to "know" the right domain without getting the request. There might also be some magic being done by the web server and the CDN before the request is even reaching AEM.
On top of that, the activate method is not called each time the service is used, since those components are used multiple times.
So I think no, there is no way to guess what the domain of the next incoming request will be when the component is activated.
BR,
Oliver
To add to #OliverGeberts answer, this information can be added to the content (i.e. page properties of the language root) or some sort of tenant configuration.
I have the following configuration for sending SOAP requests as part of a integration flow, where uriDefinedInApplicationProperties is a fixed uri, defined in 'application.properties' file :
#Bean
public MarshallingWebServiceOutboundGateway outboundSOAPGateway()
{
final MarshallingWebServiceOutboundGateway outboundGateway = new MarshallingWebServiceOutboundGateway(
uriDefinedInApplicationProperties,
requestMarshaller,
responseMarshaller);
outboundGateway.setAdviceChain(Collections.singletonList(retryOutboundGatewayAdvice));
if (soapActionCallback!= null) {
outboundGateway.setRequestCallback(soapActionCallback);
}
return outboundGateway;
}
Now i have the requirement that the URI of the remote SOAP server should be dynamically generated ( i'm planning on using message headers to store the URI).
I wanted to do something like the following, but MarshallingWebServiceOutboundGateway does not seem to support it, and i haven't been able to find how to do something similar using spring integration dsl:
#Bean
public MarshallingWebServiceOutboundGateway outboundSOAPGateway()
{
final MarshallingWebServiceOutboundGateway outboundGateway = new MarshallingWebServiceOutboundGateway(
message -> (message -> message.getHeaders().get("remote.uri.header"),
requestMarshaller,
responseMarshaller);
outboundGateway.setAdviceChain(Collections.singletonList(retryOutboundGatewayAdvice));
if (soapActionCallback!= null) {
outboundGateway.setRequestCallback(soapActionCallback);
}
return outboundGateway;
}
I have noted that MarshallingWebServiceOutboundGateway has a setUriVariableExpressions(Map<String, Expression> uriVariableExpressions) method, but i didn't find any clear documentation on what it is supposed to do and how it works.
Also i tried to do something like the following to create the outbound gateway, but it does not seem to support requestCallbacks nor advice chain.
Http.outboundGateway(message -> message.getHeaders().get("remote.uri.header"))
.messageConverters(new MarshallingHttpMessageConverter(
remoteRequestMarshaller,
remoteResponseMarshaller));
What is the best way to create a SOAP outbound gateway with retry advice and dynamically generated uri?
The advice config is not a MessageHandler responsibility. If you use Java DSL, see a second argument (a GenericEndpointSpec lambda) of the handle() you use for that MarshallingWebServiceOutboundGateway:
/**
* Configure a list of {#link Advice} objects to be applied, in nested order, to the
* endpoint's handler. The advice objects are applied only to the handler.
* #param advice the advice chain.
* #return the endpoint spec.
*/
public S advice(Advice... advice) {
Yes, I agree that MarshallingWebServiceOutboundGateway (and its super class) doesn't support URI resolution against message at the moment. Feel free to raise a GH issue to fix a gap with a SpEL configuration like we have it for the mentioned Http.outboundGateway.
Meanwhile as a workaround you can consider to implement a DestinationProvider which reads an URI from a TheadLocal store. Before calling this gateway you should consult your message and store built URI into that ThreadLocal variable.
It`s possible to register one filter in RestEasy that will works for any instance? Today I have a lot of services thats use one client
for example:
Client client = ClientBuilder.newClient();
WebTarget target = client.target(ulrBase);
ResteasyWebTarget rtarget = (ResteasyWebTarget) target;
this.servico = rtarget.proxy(UsuarioServiceClient.class);
but now I have to pass one header prop, so I create this:
public class AuthHeadersRequestFilter implements ClientRequestFilter {
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
requestContext.getHeaders().add("xx-Authorization", ((IntegraUI) UI.getCurrent()).getSessionToken());
}
}
but for all Client I need to insert this line:
client.register(new AuthHeadersRequestFilter());
So, can I configure to every place i create one client, this filter will be registered automatic?
tks
A step back
How many Client instances are you playing with?
Client instances are heavy-weight objects and you are supposed to have only a small number of instances and reuse them when possible. Have a look at the documentation:
Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application. Client instances must be properly closed before being disposed to avoid leaking resources.
Registering filters and interceptors
RESTEasy won't register filters and interceptors automatically on your Client. It happens on server side when a filter or interceptor is annotated with #Provider. But on client side, you must register the filters and interceptors manually.
Instead of registering filters and interceptors in the Client instance, you could register them in a Configuration instance and use it to create the Client instance:
Configuration config = new Configuration();
config.register(MyClientResponseFilter.class);
config.register(new AnotherClientFilter());
Client client = ClientBuilder.newClient(config);
It might be useful when creating more than one client with the same configuration.
I need to create a rest server and client.
I stumbled upon this tutorial which uses sockets. I want to be able to use REST calls, possibly HTTP, because the clients will be actually in different languages.
Instead of using Socket api from java.net.* what should i use ? if i use Socket API can I use c++ and php to communicate with this server? or should i go with REST?
any directions appreciated.
There's a lot of things you can use to create rest services, and then they can be consumed by almost anything. Of particular awesomeness is the ability to hit them in your web browser, just because we're all so familiar with them.
When I need a 'quick and dirty' rest solution, I use Restlet - I won't claim it's the only solution, but it's the easiest I've ever worked with. I've literally said in a meeting "I could have XYZ up in 10 minutes." Someone else in the meeting called me on it, and sure enough, using Restlet I was able to get a functioning REST server running with the (very simple) features I said I would get in the meeting. It was pretty slick.
Here's a barebones server that has one method, returning the current time. Running the server and hitting 127.0.0.1:12345/sample/time will return the current time.
import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.data.Protocol;
import org.restlet.routing.Router;
/**
* This Application creates an HTTP server with a singple service
* that tells you the current time.
* #author corsiKa
*/
public class ServerMain extends Application {
/**
* The main method. If you don't know what a main method does, you
* probably are not advanced enough for the rest of this tutorial.
* #param args Command line args, completely ignored.
* #throws Exception when something goes wrong. Yes I'm being lazy here.
*/
public static void main(String...args) throws Exception {
// create the interface to the outside world
final Component component = new Component();
// tell the interface to listen to http:12345
component.getServers().add(Protocol.HTTP, 12345);
// create the application, giving it the component's context
// technically, its child context, which is a protected version of its context
ServerMain server = new ServerMain(component.getContext().createChildContext());
// attach the application to the interface
component.getDefaultHost().attach(server);
// go to town
component.start();
}
// just your everyday chaining constructor
public ServerMain(Context context) {
super(context);
}
/** add hooks to your services - this will get called by the component when
* it attaches the application to the component (I think... or somewhere in there
* it magically gets called... or something...)
*/
public Restlet createRoot() {
// create a router to route the incoming queries
Router router = new Router(getContext().createChildContext());
// attach your resource here
router.attach("/sample/time", CurrentTimeResource.class);
// return the router.
return router;
}
}
And here's the 'current time resource' that it uses:
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
/**
* A resource that responds to a get request and returns a StringRepresentaiton
* of the current time in milliseconds from Epoch
* #author corsiKa
*/
public class CurrentTimeResource extends ServerResource {
#Get // add the get annotation so it knows this is for gets
// method is pretty self explanatory
public Representation getTime() {
long now = System.currentTimeMillis();
String nowstr = String.valueOf(now);
Representation result = new StringRepresentation(nowstr);
return result;
}
}
JAX-RS is the API for REST in Java. There are a lot of implementations, but the main ones are Jersey (the reference implementation), Apache's CXF and Restlet.
Usually, you don't create a server. You create a web application and deploy it on the server or servlet container. Some servlet containers are embedable into your web application, e.g. Jetty. Poppular free servlet containers are Tomcat, Glassfish, Jetty, etc.
For Restlet, it is not a servlet container. It is a framework that allow you to create a wep application with RESTful styles. So this should not be confused.
If you decide to use servlet container, then the problem is how you can create a web application with the RESTful styles. REST is not a technology - it is a design principle. It is a concept of how you should create the interface.
The design of REST is stateless so you do not need to store the state of the transaction. All information from a request should be sufficient to produce a respose to client.
There are several servlet framework that allows you to implment the REST styles easily. Some of them are very sophisticated, e.g. Spring framework.
Download JBoss 7. Problem solved.
Heres a restful service:
#Path("/myservice")
public class MyService {
#GET
#Produces(MediaTypes.TEXT_PLAIN)
public String echoMessage(#QueryParam("msg") String msg) {
return "Hello " + msg;
}
}
Create a WAR. Deploy. Open up browser and go http://myserver/myapp/myservice?msg=World. Done!
I would say go with an HTTP based RESTful service. It's rapidly becoming a defacto standard. Check my answer to this similar question for pros and cons.
This is the best one out there. Spring MVC which has lot of REST capabilities in itself. This takes just a single jar file to be included. And you are all set to use all it's capabilities. Even as simple as the below guy explained in JBOSS and much more flexibility as well.
http://java.dzone.com/articles/spring-30-rest-example
I use JBoss 6 with RestEasy. I have created a tutorial located here. I hope this helps you.
You're also welcome to see my very simple example for REST server implementation here.
I have Jersey client with a lot of functionality and now requirements are changed and I need to implement multitenancy for it.
I tried to implement automatic tenancy resolving on server side using URL of client that sent the request, but method getRemoteHost() from ServletRequest class in some cases returns only IP, but not a domain name, so it seems that I need to implement multitenancy feature also on client side and pass some parameters in query.
Is it possible to set default query parameter for the whole Jersey client instance without adding it into every method?
Yes - add a client filter that adds the parameter to every outgoing request - see http://jersey.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/client/filter/ClientFilter.html