I build a simple Jersey rest server, that handle a simple service.
In main class that start the server, i read properties file that i want to
provide/pass to jax handler classes.
The server works, i just have to make a way to share config parameters of
main class with handler of requests.
How i can do this ?
The code of main, where i read de properties file one time only:
...
public HashMap resources;
// this start the listener jersey server...
String host="http://localhost/";
int port = 9998;
URI baseUri = UriBuilder.fromUri(host).port(port).build();
ResourceConfig config = new ResourceConfig();
config.packages(true, "br.com.myserver");
config.register(MyHandler.class);
// I WANT TO ACCESS/SHARE THIS WITH THE HANDLER -> MyHandler.class
resources.put("host_user","bla bla bla");
HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, config);
System.out.println("--Press Enter to STOP the server--");
System.in.read();
Server.stop(0);
System.out.println("Server stoped!");
...
The code of MyHandler, where i want to access main properties:
#Path("myapp")
public class MyHandler
{
#POST #Path("/testep")
#Consumes("application/json")
#Produces("text/plain")
public String action1(#Context Request request, String json)
{
// HERE I WANT TO ACCESS THE RESOUCES HASHMAP OF MAIN HERE
// (how get main handler here).resources.get("host_user");
// maybe access main class, or something like
// the intention is to avoid the read of config at all requests here
System.out.println("received event:" + json);
return "event received " + json;
}
}
Any ideas will be apreciated, thanks.
Any properties you configure the ResourceConfig using it's property(key, value), will be accessible through the Configuration interface which you can inject into your resource class.
ResourceConfig config = new ResourceConfig();
config.property("host_user","bla bla bla");
...
#Path("myapp")
public class MyHandler
{
#Context
Configuration configuration;
public String action1(#Context Request request, String json) {
Map<String, Object> props = configuration.getProperties();
}
}
See Also:
Configuration Properties with Jersey for some other ideas.
Related
I'm trying to implement a restful web service using Jersey JAX-RS.
I embedded a Jetty web server and wanted to register all the controllers on it.
I based on this example:
https://nikgrozev.com/2014/10/16/rest-with-embedded-jetty-and-jersey-in-a-single-jar-step-by-step/
in which EntryPoint is the controller:
#Path("/entry-point")
public class EntryPoint {
#GET
#Path("test")
#Produces(MediaType.TEXT_PLAIN)
public String test() {
return "Test";
}
}
and this is registered using the key name "jersey.config.server.provider.classnames" as follows:
public class App {
public static void main(String[] args) throws Exception {
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
Server jettyServer = new Server(8080);
jettyServer.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(
org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
// Tells the Jersey Servlet which REST service/class to load.
jerseyServlet.setInitParameter(
"jersey.config.server.provider.classnames",
EntryPoint.class.getCanonicalName());
try {
jettyServer.start();
jettyServer.join();
} finally {
jettyServer.destroy();
}
}
}
How can I register many controllers?
If I add other controller classes as params I don't know what key name I must give to each one, because only "jersey.config.server.provider.classnames" seems to work and works once.
Thanks.
Because you can only use the property once, you need to use a comma delimited list as the value classOne, classTwo, classThree.
Another option is to use the property jersey.config.server.provider.packages and just give it a package to recursively scan
jerseyServlet.setInitParam(ServerProperties.PROVIDER_PACKAGES, "my.package.to.scan");
See ServerProperties for more properties you can set. Here PROVIDER_PACAKGES is a constant, whose string value is jersey.config.server.provider.packages. Same with the classnames property there is a constant PROVIDER_CLASSNAMES.
By declaring the package to scan, Jersey will scan that package recursively (by default) and register all #Path and #Provider annotated classes it finds in the scan.
Hello I am using vertx in java on a standalone app to read a port in my web app. I want to get the post data from a form.
My web app has a form with a post method that I am looking to read.
My logic is
Create verticle
Create http Server
Create handler request ( it does not take all the parameters in my
code)
Listen to httpServer
Expect Multipart Request in Handler
Multimap and get form attributes
I dont know what I am missing , I am new to vertx .
For some reason I cannot post code on here.
My code:
https://pastebin.com/A1hjXFb6
Make sure that your HTML form is having enctype="multipart/form-data" attribute.
Then in your vertx code:
public class loginLogic extends AbstractVerticle {
//Vertx vertx;
private HttpServer httpServer = null;
#Override
public void start() {
Router router = Router.router(vertx);
router.route().handler(BodyHandler.create().setUploadsDirectory("uploads"));
router.post("/form").handler(ctx -> {
ctx.response().putHeader("Content-Type", "text/plain");
ctx.response().setChunked(true);
for (FileUpload f : ctx.fileUploads()) {
System.out.println("f");
ctx.response().write("Filename: " + f.fileName());
ctx.response().write("\n");
ctx.response().write("Size: " + f.size());
}
ctx.response().end();
});
vertx.createHttpServer().requestHandler(router::accept).listen(8080);
}
}
I'm new to both java and jersey. Now I want to use the jersey to realize a REST services with extra processing after sending the response (specifically, sleep a fix amount of seconds and then fire a different REST request in the same servlet context, so it's unlike a REST proxy). I had googled for a while but all seems take it for granted that implicitly flushing the response at the end of method. Here are the current codes with JAXB enabled I'm struggling to work on.
#Path("/chat")
public class LoadSimulator {
#Context private UriInfo uriInfo;
#Path("/outbound/{senderAddress}/requests")
#POST
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response createOutboundSMSMessage(OutboundSMSMessageRequest inSmsReq, #PathParam("senderAddress") String senderAddress) throws JAXBException {
String requestId = UUID.randomUUID().toString();
URI uri = uriInfo.getAbsolutePathBuilder().path(requestId).build();
ObjectFactory factory = new ObjectFactory();
ResourceReference resourceReference = new ResourceReference();
resourceReference.setResourceURL(uri.toString());
JAXBElement<ResourceReference> inSmsResponse = factory.createResourceReference(resourceReference);
return Response.created(uri).entity(inSmsResponse).build();
//// want to flush or commit the response explicitly like:
// out.flush();
// out.close();
//// Then sleep for a few second and fire a new REST request
// sleep(5);
// ....
// ClientConfig config = new DefaultClientConfig();
// String response = r.path("translate").queryParams(params).get(String.class);
}
}
If you could do what you're trying to do, you would exhaust the resources on your server because every request would take X seconds and you have a finite amount of threads available before the box cries uncle.
Without commenting on why you'd want to do this; If you used the #Singleton annotation for your LoadSimulator you could set up a thread that listens on a (concurrent) queue in #PostConstruct public void init() - that gets called when your servlet starts up.
#Singleton
#Path("/chat")
public class LoadSimulator {
private Thread restCaller;
private ConcurrentLinkedQueue<MyInfo> queue = new ConcurrentLinkedQueue<MyInfo>();
...
#PostConstruct public void init()
{
restCaller = new Thread(new MyRunnable(queue));
restCaller.start();
}
...
Then in your REST call, you'd put whatever information is needed to make the second REST call on that queue, and have the aforementioned thread pulling it off and making queries.
I wrote the following code to implement a Java web service that communicates with an application written in another language on the same host:
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
#WebService(name = "MyWebService")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class MyWebService {
#WebMethod(operationName = "methodName", action = "urn:#methodName")
#WebResult(name = "result", partName = "output")
public String methodName(#WebParam(name = "param1", partName = "input") String param1,
#WebParam(name = "param2", partName = "input") String param2){
// ...do something
return "You called this service with params: " + param1 + "," + param2;
}
Since requirements are not to use an application server to expose the web service I instantiated the service from another class as follows:
Endpoint endpoint = Endpoint.create(new MyWebService());
URL url = new URL("http://localhost:7777/MyWebService");
endpoint.publish(url.toString());
Questions:
1) Which is the simplest way to secure this service with username and password considering the architecture of this project?
Any code sample would be greatly appreciated.
2) I made some research and found the use of SOAPHandler and I think it would work for me.
In the case of using the SOAPHandler class how do I add headers to the message to require authentication from the client?
Thank you in advance
thanks so much for the response that's the direction I'm following too but
when I check any of the headers for example:
SOAPHeader header = soapContext.getMessage().getSOAPPart().getEnvelope().getHeader();
Iterator<SOAPElement> iterator = header.getAllAttributes();
I get a nullpointer exception...any ideas?
I did a working program. Just to add to what you already found out, following is a way to use handler
Endpoint endpoint = Endpoint.create(new MyWebService());
Binding binding = endpoint.getBinding();
List<Handler> handlerChain = new ArrayList<Handler>(1);
handlerChain.add(new MyHandler());
binding.setHandlerChain(handlerChain);
URL url = new URL("http://localhost:7777/MyWebService");
endpoint.publish(url.toString());
MyHandler is class extending Handler interface. Alternately, you can use #HandlerChain annotation which will need an xml configuration file for handlers. Configure this for incoming messages only
public class MyHandler implements SOAPHandler{
#Override
public Set<?> getHeaders() {
// TODO Auto-generated method stub
return null;
}
#Override
public void close(MessageContext context) {
// TODO Auto-generated method stub
}
#Override
public boolean handleFault(MessageContext context) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean handleMessage(MessageContext context) {
System.out.println("Hehehe the handler");
SOAPMessageContext soapContext = (SOAPMessageContext)context;
try {
SOAPHeader header = soapContext.getMessage().getSOAPPart().getEnvelope().getHeader();
//Check there if the required data (username/password) is present in header or not and return true/false accordingly.
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
From the client side also, if your client is using JAB-WS, you will have to use client handlers. Following is a typical JAX-WS client invocation example
Dispatch<Source> dispatch = … create a Dispatch<Source>
dispatch.getBinding().setHandlerChain(chain)
Source request = … create a Source object
Source response = dispatch.invoke(request);
Here the handler in chain will add header to outgoing request. Configure this for Outgoing messages only.
What you did is fair enough.
Concerning the authentication you can just expose a method for passing user name and password as login credentials.
Once the user has provided the correct credentials the user has been authenticated.
Note: Now you must maintain session data and make sure that an incoming request is from an authenticated user. The Endpoint just deploys internally a lightweight http server. You must design you web service implementation to keep "state" among requests.
You have 2 more options.
Do the authentication at the SOAP level. I would not really recomend
it. But if you do, note that the Endpoint does not deploy a
WSDL. So you must communicate exactly to the client connecting,
the SOAP header you expect. It is possible though to write a WSDL by
yourself and "attach" it to the Endpoint.
Do the authentication at the http request level. I.e. add a token or
cookie to the http request. To be honest I do not remember if this
is easy using the Endpoint
I'm using JAX-WS reference implementation (2.1.7) and I want to trace SOAP request/responses on the client side. Actually, what I need is to examine some Http headers when I receive the response.
Following these previous questions ( Tracing XML request/responses with JAX-WS and Java JAX-WS web-service client: how log request & response xml? ), I've created my own handler to log when I send a request and receive a response:
public class SHandler implements SOAPHandler<SOAPMessageContext>
{
private static final Logger log = Logger.getLogger(SHandler.class);
#Nullable
#Override
public Set<QName> getHeaders()
{
log.debug(">>>>>>>>>>> GetHeaders");
return null;
}
#Override
public boolean handleMessage(SOAPMessageContext soapMessageContext)
{
log.debug(">>>>>>>>>>> HandleMessage");
return true;
}
#Override
public boolean handleFault(SOAPMessageContext soapMessageContext)
{
log.debug(">>>>>>>>>>> HandleFault");
return true;
}
#Override
public void close(MessageContext messageContext)
{
log.debug(">>>>>>>>>>> Close");
}
}
and I add the handler to the handler chain during the service initialisation:
#WebServiceClient(name = "MyService", targetNamespace = "http://www.whatever.com/", wsdlLocation = "file:/path/to/wsdl")
public class MyService extends Service
{
public MyService(URL wsdlLocation) {
super(...);
initializeBinding();
}
#WebEndpoint(name = "MyOperation")
public MyPort getMyPort() {
return super.getPort(new QName("http://www.whatever.com/", "MyPort"), MyPort.class);
}
private void initializeBinding() {
MyPort port = getMyPort();
BindingProvider bindingProvider = ((BindingProvider) port);
List handlerChain = bindingProvider.getBinding().getHandlerChain();
handlerChain.add(new SHandler());
bindingProvider.getBinding().setHandlerChain(handlerChain);
}
...
}
The problem is that this doesn't work at all on the client side. I don't see any logs and my handler is never executed when I send a request and receive a response.
Notice that there is no specific WSDL related to this issue because I work on an MDA platform that generates client/server artifacts from any WSDL. In addition, I cannot do this at configuration level as all is generated, so I can only do it programmatically (I've been googling this and all the solutions that I find are either the one in the original post or using the handler-chain.xml configuration file).
Am I missing something? Is there any other way of doing this?
Thanks in advance.
If you only want to look at the SOAP messages run with
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
VM argument.
Why not use #HandlerChain(file = "....") annotation?
From my pov, you can not mix constructor- and annotation-based configurations as on-deploy webservice initialization and creating new instance of your service class are performed in absolutely different contexts.
there are 2 tools that you can use to help with this:
soapui
Eclipse tcp/ip monitor
Both tools offer a proxy mode, which intercepts, logs and forwards requests and responses.