Is RESTEasy RegisterBuiltin.register necessary when using ClientResponse<T> - jboss

I am developing a REST client using JBOSS app server and RESTEasy 2.3.6. I've included the following line at the beginning of my code:
RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
Here's the rest of the snippet:
RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(host, port, AuthScope.ANY_REALM), new UsernamePasswordCredentials(userid,password));
ClientExecutor executor = createAuthenticatingExecutor(httpclient, host, port);
String uriTemplate = "http://myhost:8080/webapp/rest/MySearch";
ClientRequest request = new ClientRequest(uriTemplate, executor);
request.accept("application/json").queryParameter("query", searchArg);
ClientResponse<SearchResponse> response = null;
List<MyClass> values = null;
try
{
response = request.get(SearchResponse.class);
if (response.getResponseStatus().getStatusCode() != 200)
{
throw new Exception("REST GET failed");
}
SearchResponse searchResp = response.getEntity();
values = searchResp.getValue();
}
catch (ClientResponseFailure e)
{
log.error("REST call failed", e);
}
finally
{
response.releaseConnection();
}
private ClientExecutor createAuthenticatingExecutor(DefaultHttpClient client, String server, int port)
{
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
HttpHost targetHost = new HttpHost(server, port);
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
BasicHttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.AUTH_CACHE, authCache);
// Create ClientExecutor.
ApacheHttpClient4Executor executor = new ApacheHttpClient4Executor(client, localContext);
return executor;
}
The above is a fairly simple client that employs the ClientRequest/ClientResponse<T> technique. This is documented here. The above code does work (only left out some trivial variable declarations like host and port). It is unclear to me from the JBOSS documentation as to whether I need to run RegisterBuiltin.register first. If I remove the line completely - my code still functions. Do I really need to include the register method call given the approach I have taken? The Docs say I need to run this once per VM. Secondly, if I am required to call it, is it safe to call more than one time in the same VM?
NOTE: I do understand there are newer versions of RESTEasy for JBOSS, we are not there yet.

Related

HTTPClient 4.x Auth cache not set in the context

I am using HttpClient 4.5.x to call a SOAP web service with NTLM authentication.
Authentication happens successfully. It is a 3 way handshake.
For example, if i do post-request including images or other data content, then for each handshake request, the data is sent.
One recommendation from the HttpClients material online is to do a cheap request first, and use the same client context object for the subsequent big size request.
It also says this in the documentation - As of version 4.1, HttpClient automatically caches information about hosts it has successfully authenticated.
I tried the same. I have both these requests subsequently happening in the same method, and the same thread. The (default) caching does not happen. Both times the 3-way handshake was happening.
In the log I see the following statement
[org.apache.http.client.protocol.RequestAuthCache] Auth cache not set in the context
May be this default does not work for NTLM.
Is there any flag to turn the caching on?
Or should I create AuthCache myself and maintain? It looks like only for preemptive authentication, one creates auth cache. So, I am doubtful if it applies to my case.
private void callServiceWithAuthentication (ByteArrayEntity entity)
{
try {
/*
AuthScope authScope = new AuthScope("WEBSERVICE-HOST", 443, AuthScope.ANY_REALM, "ntlm");
*/
CloseableHttpClient httpclient = HttpClients.createDefault();
NTCredentials ntCredentials = new NTCredentials(this.userName, this.password, null, "DOMAIN");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, ntCredentials);
httpClientContext = HttpClientContext.create();
httpClientContext.setCredentialsProvider(credentialsProvider);
HttpHost targetHost = new HttpHost ("WEBSERVICE_HOST", 443);
// First cheap-cost request
HttpGet httpGet = new HttpGet ("WEBSERVICE_URL");
CloseableHttpResponse httpResponse = httpclient.execute(httpGet, httpClientContext);
HttpEntity getResponseEntity = httpResponse.getEntity();
// Following real costly post request
HttpPost post = new HttpPost("WEBSERVICE_URL");
post.setEntity(entity);
// Execute request
try {
CloseableHttpResponse response = httpclient.execute(post, httpClientContext);
StatusLine statusLine = response.getStatusLine();
HttpEntity rentity = response.getEntity();
System.out.println ("HTTP Response Code: " + statusLine.getStatusCode());
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
System.out.println (rentity.getContent());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
// Release current connection to the connection pool once you are done
post.releaseConnection();
}
}
catch (Exception e) {e.printStackTrace();}
finally {
}
}
I had to have the first response entity consume before the second request. Then the second request did not do the (3-way handshake) authentication again.
EntityUtils.consume(getResponseEntity);
I have more cleanup to do

Curator Framework doesn't allow me check Connection

I'm checking the connection of a CuratorFramework instance, when i do in debug mode it passes fine, but when I do in running mode it pass through the verification considering the condition as false.
curatorFramework.getZookeeperClient().isConnected();
Is something wrong with the code? This is how i create the instance:
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 1);
CuratorFramework curatorFramework= CuratorFrameworkFactory.newClient(host, retryPolicy);
curatorFramework.start();
I can't spot anything obviously wrong with your code, however, I'd suggest giving the CuratorFrameworkFactory a try for building your CuratorFramework instance like so:
String connectionString = ....
CuratorFramework client = CuratorFrameworkFactory.builder()
.namespace("my_namespace")
.connectString(connectionString )
.retryPolicy(new ExponentialBackoffRetry(1000, 1))
.build();
client.start();
I'd also suggest testing your code with the Curator's built-in TestingServer to ensure the problem isn't with the ZK cluster you're currently testing against. To setup and connect to the Curator test server, simply use something like this:
TestingServer zkTestServer = new TestingServer(31313);
CuratorFramework client = CuratorFrameworkFactory.builder()
.namespace("my_namespace")
.connectString(zkTestServer.getConnectString())
.retryPolicy(new ExponentialBackoffRetry(1000, 1))
.build();
client.start();
you should connect to zk after you start the curatorFramework using curatorFramework.blockUntilConnected(), and then get client and check connection status. Something likes below:
...
curatorFramework.start();
try {
curatorFramework.blockUntilConnected(3, TimeUnit.SECONDS);
if (curatorFramework.getZookeeperClient().isConnected()) {
System.out.println(curatorFramework.getState());
return;
}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
...

JBoss return org.jboss.remoting.ProtocolException: Too many channels open

My program encountered a error:
"org.jboss.remoting3.ProtocolException: Too many channels open"
I have search from internet for some solutions to fix this error.Unfortunately, the suggestions from others is not working for me.
Below is the Code on how I call the jndi remote and the properties that I have used.
public static void createUser(String loginID) throws Exception {
Hashtable props = new Hashtable();
try {
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
props.put(Context.PROVIDER_URL, "remote://" + localhost:4447);
props.put("jboss.naming.client.ejb.context", "true");
props.put(Context.SECURITY_PRINCIPAL, "userJBoss");
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
context = new InitialContext(props);
context.lookup("ejb:/createUserOperation/CreateUserGenerator!password.api.CreateUserService");
.....
......
LOGGER.info("DONE");
} catch (Exception e) {
LOGGER.error("ERROR");
} finally {
context.close();
}
}
Due to some certain reason I am not able to show all the content of the method.
The "createUser" will be call everytime when there is a needed of create new user. It will be call up to hundred or thousand time.
I did always close the connection when every time it finish execute the method.
Let say I have call the method for 100 times, some of the users will be created successfully whereas some of the users will be failed.
Error below will prompt to me:
2014-12-04 17:23:23,026 - ERROR [Remoting "config-based-naming-client-endpoint" task-4] (org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver- Line:134) - Failed to open channel for context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext#bbaebd6, receiver=Remoting connection EJB receiver [connection=Remoting connection <78e43506>,channel=jboss.ejb,nodename=webdev01]} org.jboss.remoting3.ProtocolException: Too many channels open
Once the error occurred, it required me to restart my jboss.And it comes again after sometimes.
Appreciate it if anyone wound able to help on my problem faced.
Thanks
You are using mixture of context properties.
This should be enough
final Properties ejbProperties = new Properties();
ejbProperties.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
ejbProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
ejbProperties.put("remote.connections", "1");
ejbProperties.put("remote.connection.1.host", "localhost");
ejbProperties.put("remote.connection.1.port", "4447");
ejbProperties.put("remote.connection.1.username", "ejbuser");
ejbProperties.put("remote.connection.1.password", "ejbuser123!");
final EJBClientConfiguration ejbClientConfiguration = new PropertiesBasedEJBClientConfiguration(ejbProperties);
final ConfigBasedEJBClientContextSelector selector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);
EJBClientContext.setSelector(selector);
final Context context = new InitialContext(ejbProperties);
// lookup
Foo proxy = context.lookup("ejb:/createUserOperation/CreateUserGenerator!password.api.CreateUserService");
when using org.jboss.ejb.client.naming it creates EJBClientContext object.
When closing context you are closing InitialContext not EJBClientContext
to close EJBClientContext:
EJBClientContext.getCurrent().close();
There is a known JBoss bug (EAP 6, AS 7) whereby opening and closing too many InitialContext instances too quickly causes the following error:
ERROR: Failed to open channel for context EJBReceiverContext
Instead of:
final Properties properties = ...
final Context context = new InitialContext( properties );
Try caching the context for a set of properties instead:
private Map<Integer, InitialContext> initialContexts = new HashMap<>();
final Context context = getInitialContext(properties);
private InitialContext getInitialContext(final Properties properties) throws Exception {
final Integer hash = properties.hashCode();
InitialContext result = initialContexts.get(hash);
if (result == null) {
result = new InitialContext(properties);
initialContexts.put(hash, result);
}
return result;
}
Remember to call close() when the context is no longer necessary.

httpunit PutMethodWebRequest throws IOException; bad file descriptor

Could someone explain why this httpunit test case keeps failing in wc.getResponse with "bad file descriptor". I added the is.close() as a guess and moved it before and after the failure but that had no effect. This tests put requests to a Dropwizard app.
public class TestCircuitRequests
{
static WebConversation wc = new WebConversation();
static String url = "http://localhost:8888/funl/circuit/test.circuit1";
#Test
public void testPut() throws Exception
{
InputStream is = new FileInputStream("src/test/resources/TestCircuit.json");
WebRequest rq = new PutMethodWebRequest(url, is, "application/json");
wc.setAuthentication("FUNL", "foo", "bar");
WebResponse response = wc.getResponse(rq);
is.close();
}
No responses? So I'll try myself based on what I learned fighting this.
Httpunit is an old familiar tool that I'd use if I could. But it hasn't been updated in more than two years, so I gather its support for #PUT requests isn't right.
So I converted to Jersey-client instead. After a bunch of struggling I wound up with this code which does seem to work:
#Test
public void testPut() throws Exception
{
InputStream is = new FileInputStream("src/test/resources/TestCircuit.json");
String circuit = StreamUtil.readFully(is);
is.close();
Authenticator.setDefault(new MyAuthenticator());
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
com.sun.jersey.api.client.WebResource service = client.resource(url);
Builder builder = service.accept(MediaType.APPLICATION_JSON);
builder.entity(circuit, MediaType.APPLICATION_JSON);
builder.put(String.class, circuit);
return;
}
This intentionally avoids JAX-RS automatic construction of beans from JSON strings.

Socket connection gets closed for no apparent reason

I am trying to implement Facebook X_FACEBOOK_PLATFORM SASL mechanism so I could integrate Facebook Chat to my application over XMPP.
Here is the code:
var ak = "my app id";
var sk = "access token";
var aps = "my app secret";
using (var client = new TcpClient())
{
client.Connect("chat.facebook.com", 5222);
using (var writer = new StreamWriter(client.GetStream())) using (var reader = new StreamReader(client.GetStream()))
{
// Write for the first time
writer.Write("<stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" to=\"chat.facebook.com\"><auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-FACEBOOK-PLATFORM\" /></stream:stream>");
writer.Flush();
Thread.Sleep(500);
// I am pretty sure following works or at least it's not what causes the error
var challenge = Encoding.UTF8.GetString(Convert.FromBase64String(XElement.Parse(reader.ReadToEnd()).Elements().Last().Value)).Split('&').Select(s => s.Split('=')).ToDictionary(s => s[0], s => s[1]);
var response = new SortedDictionary<string, string>() { { "api_key", ak }, { "call_id", DateTime.Now.Ticks.ToString() }, { "method", challenge["method"] }, { "nonce", challenge["nonce"] }, { "session_key", sk }, { "v", "1.0" } };
var responseString1 = string.Format("{0}{1}", string.Join(string.Empty, response.Select(p => string.Format("{0}={1}", p.Key, p.Value)).ToArray()), aps);
byte[] hashedResponse1 = null;
using (var prov = new MD5CryptoServiceProvider()) hashedResponse1 = prov.ComputeHash(Encoding.UTF8.GetBytes(responseString1));
var builder = new StringBuilder();
foreach (var item in hashedResponse1) builder.Append(item.ToString("x2"));
var responseString2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}&sig={1}", string.Join("&", response.Select(p => string.Format("{0}={1}", p.Key, p.Value)).ToArray()), builder.ToString().ToLower()))); ;
// Write for the second time
writer.Write(string.Format("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">{0}</response>", responseString2));
writer.Flush();
Thread.Sleep(500);
MessageBox.Show(reader.ReadToEnd());
}
}
I shortened and shrunk the code as much as possible, because I think my SASL implementation (whether it works or not, I haven't had a chance to test it yet) is not what causes the error.
I get the following exception thrown at my face: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
10053
System.Net.Sockets.SocketError.ConnectionAborted
It happens every time I try to read from client's stream for the second time. As you can see i pause a thread here so Facebook server has enough time to answer me, but I used asynchronous approach before and I encountered the exact same thing, so I decided to try it synchronously first. Anyway actual SASL mechanism implementation really shouldn't cause this because if I don't try to authenticate right away, but I send the request to see what mechanisms server uses and select that mechanism in another round of reading and writing, it fails, but when I send mechanism selection XML right away, it works and fails on whatever second I send.
So the conclusion is following: I open the socket connection, write to it, read from it (first read works both sync and async), write to it for the second time and try to read from it for the second time and here it always fails. Clearly then, problem is with socket connection itself. I tried to use new StreamReader for second read but to no avail. This is rather unpleasant since I would really like to implement facade over NetworkStream with "Received" event or something like Send(string data, Action<string> responseProcessor) to get some comfort working with that stream, and I already had the implementation, but it also failed on second read.
Thanks for your suggestions.
Edit: Here is the code of facade over NetworkStream. Same thing happens when using this asynchronous approach, but couple of hours ago it worked, but for second response returned same string as for first. I can't figute out what I changed in a meantime and how.
public void Send(XElement fragment)
{
if (Sent != null) Sent(this, new XmppEventArgs(fragment));
byte[] buffer = new byte[1024];
AsyncCallback callback = null;
callback = (a) =>
{
var available = NetworkStream.EndRead(a);
if (available > 0)
{
StringBuilder.Append(Encoding.UTF8.GetString(buffer, 0, available));
NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
}
else
{
var args = new XmppEventArgs(XElement.Parse(StringBuilder.ToString()));
if (Received != null) Received(this, args);
StringBuilder = new StringBuilder();
// NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
}
};
NetworkStream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
NetworkStreamWriter.Write(fragment);
NetworkStreamWriter.Flush();
}
The reader.ReadToEnd() call consumes everything until end-of-stream, i.e. until TCP connection is closed.