Grizzly PUT request with json body fails - java

I have the java server on the cloud running. Everything is ok with GET and DELETE requests, but not ok with the PUT request. I have the following PUT request handler
#PUT
#JSONP(queryParam = "callback")
public void putEvent(String eventJson) throws Exception {
Event event = new ObjectMapper().readValue(eventJson, Event.class);
EventDao.getInstance().saveOrUpdateEvent(event);
}
And here is the Server class
public static final String BASE_API_URI = "http://localhost:8080/myrest-api/";
public boolean getFileCacheEnabled() {
return false;
}
public static void main(String[] args) throws Exception {
Server server = new Server();
final HttpServer httpServer = server.startServer();
System.out.println("Press enter to stop the server...");
System.in.read();
httpServer.shutdown();
}
public HttpServer startServer() {
final ResourceConfig rc = new ResourceConfig().packages("com.myrest.events");
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_API_URI), rc);
server.getServerConfiguration().addHttpHandler(getHttpHandler(), "/page");
return server;
}
public HttpHandler getHttpHandler() {
StaticHttpHandler handler = new StaticHttpHandler("src/main/resources/webapp/");
handler.setFileCacheEnabled(getFileCacheEnabled());
return handler;
}
When I send PUT request with following JSON body
{
"name":"SimpleName",
"description":"SimpleDescription",
"author":"Me"
}
I get
Status: 500 Request failed
Although when I deploy the app locally, and try the same everything is fine. Btw I tried POST request instead, I get the same error.

Related

spring tcp socket , authorizing clients and handle pending response

The Spring framework support tcp connection as well , i wrote code below to setup a simple socket server , i am confused about adding below futures to my socket server :
authorizing clients based on a unique identifier ( for example a client secret received from client, maybe using TCP Connection Events )
send a message directly to specific client (based on identifier)
broadcast a message
UPDATE :
Config.sendMessage added to send message to single client
Config.broadCast added to broadcast message
authorizeIncomingConnection to authorize clients , accept or reject connections
tcpConnections static filed added to keep tcpEvent sources
Questions !
is using tcpConnections HashMap good idea ?!
is the authorization method i implemented a good one ?!
Main.java
#SpringBootApplication
public class Main {
public static void main(final String[] args) {
SpringApplication.run(Main.class, args);
}
}
Config.java
#EnableIntegration
#IntegrationComponentScan
#Configuration
public class Config implements ApplicationListener<TcpConnectionEvent> {
private static final Logger LOGGER = Logger.getLogger(Config.class.getName());
#Bean
public AbstractServerConnectionFactory AbstractServerConnectionFactory() {
return new TcpNetServerConnectionFactory(8181);
}
#Bean
public TcpInboundGateway TcpInboundGateway(AbstractServerConnectionFactory connectionFactory) {
TcpInboundGateway inGate = new TcpInboundGateway();
inGate.setConnectionFactory(connectionFactory);
inGate.setRequestChannel(getMessageChannel());
return inGate;
}
#Bean
public MessageChannel getMessageChannel() {
return new DirectChannel();
}
#MessageEndpoint
public class Echo {
#Transformer(inputChannel = "getMessageChannel")
public String convert(byte[] bytes) throws Exception {
return new String(bytes);
}
}
private static ConcurrentHashMap<String, TcpConnection> tcpConnections = new ConcurrentHashMap<>();
#Override
public void onApplicationEvent(TcpConnectionEvent tcpEvent) {
TcpConnection source = (TcpConnection) tcpEvent.getSource();
if (tcpEvent instanceof TcpConnectionOpenEvent) {
LOGGER.info("Socket Opened " + source.getConnectionId());
tcpConnections.put(tcpEvent.getConnectionId(), source);
if (!authorizeIncomingConnection(source.getSocketInfo())) {
LOGGER.warn("Socket Rejected " + source.getConnectionId());
source.close();
}
} else if (tcpEvent instanceof TcpConnectionCloseEvent) {
LOGGER.info("Socket Closed " + source.getConnectionId());
tcpConnections.remove(source.getConnectionId());
}
}
private boolean authorizeIncomingConnection(SocketInfo socketInfo) {
//Authorization Logic , Like Ip,Mac Address WhiteList or anyThing else !
return (System.currentTimeMillis() / 1000) % 2 == 0;
}
public static String broadCast(String message) {
Set<String> connectionIds = tcpConnections.keySet();
int successCounter = 0;
int FailureCounter = 0;
for (String connectionId : connectionIds) {
try {
sendMessage(connectionId, message);
successCounter++;
} catch (Exception e) {
FailureCounter++;
}
}
return "BroadCast Result , Success : " + successCounter + " Failure : " + FailureCounter;
}
public static void sendMessage(String connectionId, final String message) throws Exception {
tcpConnections.get(connectionId).send(new Message<String>() {
#Override
public String getPayload() {
return message;
}
#Override
public MessageHeaders getHeaders() {
return null;
}
});
}
}
MainController.java
#Controller
public class MainController {
#RequestMapping("/notify/{connectionId}/{message}")
#ResponseBody
public String home(#PathVariable String connectionId, #PathVariable String message) {
try {
Config.sendMessage(connectionId, message);
return "Client Notified !";
} catch (Exception e) {
return "Failed To Notify Client , cause : \n " + e.toString();
}
}
#RequestMapping("/broadCast/{message}")
#ResponseBody
public String home(#PathVariable String message) {
return Config.broadCast(message);
}
}
Usage :
Socket Request/Response Mode
notify single client
http://localhost:8080/notify/{connectionId}/{message}
broadCast
http://localhost:8080/broadCast/{message}
The TcpConnectionOpenEvent contains a connectionId property. Each message coming from that client will have the same property in the IpHeaders.CONNECTION_ID message header.
Add a custom router that keeps track of the logged-on state of each connection.
Lookup the connection id and if not authenticated, route to a challenge/response subflow.
When authenticated, route to the normal flow.
To use arbitrary messaging (rather than request/response) use a TcpReceivingChannelAdapter and TcpSendingMessageHandler instead of an inbound gateway. Both configured to use the same connection factory. For each message sent to the message handler, add the IpHeaders.CONNECTION_ID header to target the specific client.
To broadcast, send a message for each connection id.

Challenges performing basic HTTP authentication on RPC SOAP client

Been trying to follow some online examples as I need to do basic authentication on a webservice client.
I generated the stub classes of the project using wsimport and tried passing the authentication credentials using javax.xml.rpc.stub class but casting the proxy class throws a java.lang.ClassCastException:
com.sun.proxy.$Proxy29 cannot be cast to javax.xml.rpc.Stub.
please can anyone review this code and point me in the right direction if am doing something wrong.
public class WebClientTester
{
public static void main(String[] args)
{
doNameEnquiry("XXXXXXXXX");
}
public static void doNameEnquiry(String acct)
{
boolean txnOk = false;
try
{
String str = "http://XXX.XXX.XXX.XXX/GwHolderService.svc?wsdl";
URL url = new URL(str.substring(0, str.indexOf("?")));
QName qname = new QName("http://tempuri.org/", "GwHolderService");
Service service = Service.create(url, qname);
SInfoHolder port = (SInfoHolder) service.getPort(SInfoHolder.class);
((javax.xml.rpc.Stub) port)._setProperty(javax.xml.rpc.Stub.USERNAME_PROPERTY, "myUser");
((javax.xml.rpc.Stub) port)._setProperty(javax.xml.rpc.Stub.PASSWORD_PROPERTY, "myPwd");
InfoHolderRequest request = new InfoHolderRequest();
request.setHolderAccountNumber(acct);
InfoHolderResponse response = port.infoHolder(request);
// System.out.println("authenticated: "+
// response.getRespMessageCode());
System.out.println("******************END RESPONSE***********");
System.out.println("responseCode: " + response.getCoderesp());
System.out.println(processResponseXML(response));
System.out.println("******************LIST DETAILS***********");
listDetails(processResponseXML(response));
}
catch (Exception ex)
{
ex.printStackTrace();
}
// return txnOk;
}
}

When using http2 in okhttp, why multi requests to the same host didn't use just one connectoin

I would like to test okhttp's http2 function. And I make multi requsts to same host in async style. But, I found that, it involved multi connections, since the protocol is h2, It should use just one connection, right?
The code is below.
Ah, I'm using okhttp2.5
public class Performance {
private final OkHttpClient client = new OkHttpClient();
private final Dispatcher dispatcher = new Dispatcher();
private final int times = 20;
public Performance(){
dispatcher.setMaxRequestsPerHost(2);
client.setDispatcher(dispatcher);
// Configure the sslContext
// MySSLSocketFactory mySSLSocketFactory = new MySSLSocketFactory();
// client.setSslSocketFactory(mySSLSocketFactory);
// client.setHostnameVerifier(new HostnameVerifier() {
// public boolean verify(String s, SSLSession sslSession) {
// return true;
// }
// });
}
public void run()throws Exception{
for(int i=0; i<times; i++) {
Request request = new Request.Builder()
.url("https://http2bin.org/delay/1")
.build();
client.newCall(request).enqueue(new Callback() {
public void onFailure(Request request, IOException e) {
e.printStackTrace();
}
public void onResponse(Response response) throws IOException {
System.out.println(response.headers().get("OkHttp-Selected-Protocol"));
}
});
}
}
public static void main(String[] args)throws Exception{
Performance performance = new Performance();
performance.run();
}
}
There's a bug in OkHttp where multiple simultaneous requests each create their own socket connection, rather than coordinating a shared connection. This only happens when the connections are created simultaneously. Work around by yielding 500ms before the 2nd connection.

How do I decode the response from an http request and use the content in netty?

This is related to this question, but I'm trying to break my problem into smaller steps.
I'm trying to write a simple http server (server A) using netty that receives an http request, makes an http request to another server (server B), and then copies the content in the response into the response to the initial request. I know there are some examples of how to do this, such as LittleProxy, but the code is fairly complex, and since I'm a n00b to netty, I'm trying to make my first code as simple as possible without getting off into the weeds.
For now, I'm ignoring all concerns about concurrency, and only have one channel established from server A to server B (I know this will break horribly with concurrent requests, but it makes my initial task simpler).
My approach is the following:
Set up client bootstrap and connect to server B running on localhost port 18080. Get the corresponding channel.
Start server A listening on port 2080 with a pipeline that decodes the http request and then writes to the channel going to server B.
Add a listener to the resulting channel future that will copy the content of the response from server B to the response to the original client's request to server A.
Here's the code I have (very short) in which I'm trying to do exactly what I describe above. My problem is that I don't know how to copy the response from server B to the response from server. The one way I have figured out to do this results in an IllegalArgumentException when I write to the original client in the response sent by server A (I checked the content of the ChannelBuffer, and the correct text was returned by the proxied server). I have pasted a partial stack trace of the exception below. Other comments welcome, as there may be other mistakes I'm making besides the obvious lack of locking on the channel to server B:
public class NettyExample {
private static Channel channel;
private static Map<Channel, Channel> proxyToClient = new ConcurrentHashMap<Channel, Channel>();
public static void main(String[] args) throws Exception {
ChannelFactory clientFactory =
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
final ClientBootstrap cb = new ClientBootstrap(clientFactory);
cb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new HttpRequestEncoder(),
new HttpResponseDecoder(),
new ResponseHandler());
}
});
ChannelFuture cf = cb.connect(new InetSocketAddress("localhost", 18080));
channel = cf.awaitUninterruptibly().getChannel();
ChannelFactory factory =
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ServerBootstrap sb = new ServerBootstrap(factory);
sb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new HttpRequestDecoder(),
new RequestHandler());
}
});
sb.setOption("child.tcpNoDelay", true);
sb.setOption("child.keepAlive", true);
sb.bind(new InetSocketAddress(2080));
}
private static class ResponseHandler extends SimpleChannelHandler {
#Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
final HttpResponse proxyResponse = (HttpResponse) e.getMessage();
Channel clientChannel = proxyToClient.get(e.getChannel());
HttpResponse clientResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
clientResponse.setContent(proxyResponse.getContent());
clientChannel.write(clientResponse).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
Channel ch = future.getChannel();
ch.close();
}
});
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
}
}
private static class RequestHandler extends SimpleChannelHandler {
#Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
final HttpRequest request = (HttpRequest) e.getMessage();
System.out.println("calling client channel");
proxyToClient.put(channel, e.getChannel());
channel.write(request);
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
}
}
}
This relay call seems to work, up to the point of calling clientChannel.write(clientResponse). There, the following exception is generated:
java.lang.IllegalArgumentException: unsupported message type: class org.jboss.netty.handler.codec.http.DefaultHttpResponse
at org.jboss.netty.channel.socket.nio.SocketSendBufferPool.acquire(SocketSendBufferPool.java:53)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.write0(AbstractNioWorker.java:468)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromTaskLoop(AbstractNioWorker.java:432)
You need to setup a client pipeline to wait for the response and then write it as your response.
See the snoop client example; specifically, HttpSnoopClientHandler.

Jetty + Jersey embeded server not working if launched from JAR

I am trying to launch a Jetty server from a class. When I try to run it from eclipse it works fine. If I embed it to a JAR the jetty server starts, but when I make a request it return a 500 code response. Here is my class:
#GET
#Path("test")
#Produces(MediaType.APPLICATION_JSON)
public String echo(#QueryParam("testParam")String test){
return test;
}
private Server server;
public synchronized void start(int port) throws Exception {
if (server != null) {
throw new IllegalStateException("Server is already running");
}
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
Map<String,Object> initMap = new HashMap<String, Object>();
initMap.put("com.sun.jersey.api.json.POJOMappingFeature", "true");
initMap.put("com.sun.jersey.config.property.packages", "the.class.package");
context.addServlet(new ServletHolder(new ServletContainer(new PackagesResourceConfig(initMap))), "/*");
this.server = new Server(port);
this.server.setHandler(context);
this.server.start();
}
public static void main(String[] args) throws Exception {
if(args.length != 1) {
System.out.println("AnnotatorServer <port>");
System.exit(-1);
}
JettyServer server = new JettyServer();
server.start(Integer.parseInt(args[0]));
}
When I try to launch it embedded in a JAR, the server starts, but when I access the method, I get the following exception:
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class java.lang.String, and Java type class java.lang.String, and MIME media type application/octet-stream was not found
Do you have any idea why is this happening?? Thank you!
The problem was on the POM file. The dependency was overwriting some files in Meta-Inf/service. Found the solution to Jersey exception only thrown when depencencies assembled into a single jar

Categories

Resources