Finding JNP port in JBoss from Servlet - servlets

I have a servlet running in JBoss (4.2.2.GA and 4.3-eap) that needs to connect to an EJB to do work.
In general this code works fine to get the Context to connect and make RMI calls (all in the same server).
public class ContextFactory
{
public static final int DEFAULT_JNDI_PORT = 1099;
public static final String DEFAULT_CONTEXT_FACTORY_CLASS = "org.jnp.interfaces.NamingContextFactory";
public static final String DEFAULT_URL_PREFIXES = "org.jboss.naming:org.jnp.interfaces";
public Context createContext(String serverAddress)
{
//combine provider name and port
String providerUrl = serverAddress + ":" + DEFAULT_JNDI_PORT;
//Set properties needed for Context: factory, provider, and package prefixes.
Hashtable<String, String> env = new Hashtable<String, String>(3);
env.put(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_CONTEXT_FACTORY_CLASS);
env.put(Context.PROVIDER_URL, providerUrl);
env.put(Context.URL_PKG_PREFIXES, DEFAULT_URL_PREFIXES);
return new InitialContext(env);
}
Now, when I change the JNDI bind port from 1099 in server/conf/jboss-service.xml I can't figure out how to programatically find the correct port for the providerUrl above.
I've dumped System.getProperties() and System.getEnv() and it doesn't appear there.
I'm pretty sure I can set it in server/conf/jndi.properties as well, but I was hoping to avoid another magic config file.
I've tried the HttpNamingContextFactory but that fails "java.net.ProtocolException: Server redirected too many times (20)"
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.HttpNamingContextFactory");
env.put(Context.PROVIDER_URL, "http://" + serverAddress + ":8080/invoker/JNDIFactory");
Any ideas?

The information about the port is stored on JBoss as an MBean property. The problem is that in order to read this property you need an access to MBeans, which requires the port number...
I think that the only way to get this port number is to read the configuration file itself and extract the port number. It is not very elegant, so you may prefere to create in web.xml file for your servlet and store the port number there.
You may also use JBoss HTTP invoker, which tunnels requests to 1099 port through port 8080 (default HTTP port), please note however that you need to secure this connector. In this case the port will be always the same as your HTTP port.

Related

Azure Functions: An existing connection was forcibly closed by the remote host. Already using static HttpClient

My function invocations keep failing with the error message An existing connection was forcibly closed by the remote host. According to this to mitigate this problem I am to use static Http Clients, which I am already doing, but still the error keeps occurring.
However, I do have 4 of those static clients, which I guess is more than strictly 1. But still I would have thought to fare better with 4 static ones than with multiple (non-static) instances.
I would like to really have only 1 client but I do not know how to make it work. There is one function app which as the below helper class defined in it. In Addition there are 3 services which have been extracted to separate class libraries (because they are used in different projects also) I include in my function app and use via DI. The function app and all of the 3 libs include the below helper class.
public static class Http
{
private static HttpClient _client = new HttpClient();
public static async Task<HttpResponseMessage> GetAsync(string url, Dictionary<string, string>? headers = null)
{
var req = new HttpRequestMessage(HttpMethod.Get, url);
if (headers != null) req._addRequestHeaders(headers);
var response = await _client.SendAsync(req);
response.EnsureSuccessStatusCode();
return response;
}
}
The services in the libs use HTTP to do their own stuff. How would I be able to have the app and all of the libs it references to use the same static http client?
Or do you think the multiple static http classes are not the cause of the problem? There is no such error when running the function app locally in vs code (i.e outside of Azure).
Cheers
Or do you think the multiple static http classes are not the cause of the problem?
This. The error code you're seeing is WSAECONNRESET (10054):
Connection reset by peer.
An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
The fact that you're seeing an exception for this indicates it's an unexpected reset (there are other times when WSAECONNRESET is normal, and HttpClient handles those for you).
There's a lot of possible reasons for unexpected resets. If it's always happening, it could be a security (TLS) setting mismatch, or a malformed request. If it's sometimes happening, it could just be another service restarting/crashing at just the wrong time. Which happens in the cloud, and your service should retry.
There is no such error when running the function app locally in vs code (i.e outside of Azure).
The next thing I'd try is to turn the logging up to 11.

How to get ip public AWS in Cloudify

Using in my script file .sh:
ctx logger info $(ctx instance host_ip)
I get the private IP of my instance on AWS. How do I get the public IP?
Short answer is that as of right now you cannot, but the feature is planned.
More complete answer -
ctx.instance.host_ip maps to a compute node instance's runtime property ctx.instance.runtime_properties[ip]. By convention this is a private ip address.
This property is set if the current node is of, or is derived from, the type cloudify.nodes.Compute, or if the current node has a relationship of, or is derived from, the type cloudify.relationships.contained_in that has a target of node type, or derived from, cloudify.nodes.Compute.
AWS plugin sets the runtime property on node type cloudify.aws.nodes.Instance ctx.instance.runtime_properties['public_ip_address'].
In the meantime, the best solution is to us a script in a lifecycle operation to set a runtime property on the needed node that need's the public IP such as you will find here.
You can get public IP address in the following way:
public_address=$(ctx instance public_ip_address)
ctx logger info "Public IP address is ${public_address}"

Unable to use WebService specifing the URI through code

I have two PCs conected with a LAN. Firewall ports are opened.
I'm running a WebService on A machine, using IIS. Of course, I can access the WebService (on A) through the Web Browser on the B machine, so I'm sure the WebService can be accessed remotely.
Now, I'm running a console app on B machine, developed in vb.net, which will access the WebService of A machine.
Both, the console app and the WebService, has been developed on VS2010.
Creating the reference on the project, I can see and use the WebService. But I need to specify on code the URI due to the WebService may change its location.
The code indicating the URI manually:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13:8080")
This line throw an exception with the message that did not find any element with the name indicated. I have tried too, without success, the following lines:
This one:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13")
And this one:
Dim myService As New MiServicioWeb.WebServiceSoapClient("192.168.1.13:8080/ServicioWeb.asmx")
But the result is always the same.
Some user (raja) wrote an answer a few days ago indicating that this should work, but I don't know the reason why does not work in my case.
As I said before, if I create the reference on the project, and I use the following line of code:
Dim myService As New MiServicioWeb.WebServiceSoapClient()
It works!, but what I need is to set the URI manually...
Some help will be thankful.
if not already present, you need to modify the proxy class to have a constructor that can take a Uri and set it. This Uri needs to be supplied to the proxy.
Dim uriFromConfig as String;
// read uriFromConfig from config or set it accordingly.
Dim myService As New MiServicioWeb.ServicioWebSoapClient(uriFromConfig);
this way, any ASMX can be called, as long as the right Uri is provided.
in summary to call a webservice hosted on machine with IP a.b.c.d from another machine:
Give the Proxy Uri with the IP Address. a.b.c.d
Open the port (50594) you're using in the machine hosting the web service from the Firewall settings.
Verify if the asmx is accesible by typing http://a.b.c.d:50594/ServicioWeb.asmx from the browser of the client machine. (not the machine hosting the web service)
if #3 is successful, then you'll see a nice page on the browser.
your client app should also be able to connect now.

Client-Server communication in REST, Spring (RestTemplate): getting 404 error

I am trying to setup a Client-Server communication in REST, Spring.
In the client side I have the code:
Map<String, Double> variable = new HashMap<String, Double>(1);
variable.put(newTicket.getMovieName(),newTicket.getTicketPrice());
try{
Boolean rresult = restTemplate.getForObject("http://localhost:8081/SpringMVCMerchant/movieTheater.htm", Boolean.class, variable);
In the server side I have the code (to receive the above 'variable', and get the below boolean as a return object):
#ResponseBody
#RequestMapping(value="/movieTheater/", method=RequestMethod.GET)
public boolean getCustomerInput(Map<String, Double> input) {
return transactionService.addTransaction(input);
}
I am not sure if the above syntax is correct. When I am running the two servers, I am getting the following error at the client side(8080):
GET request for "http://localhost:8081/SpringMVCMerchant/movieTheater.htm" resulted in 404 (Not Found); invoking error handler
Please let me know what I am missing here, and what changes I need to make in my code.
Thanks in advance!
I guess you are using the wrong url to call the Web Service
http://localhost:8081/SpringMVCMerchant/movieTheater.htm
This ends with .htm whereas your RequestMapping does not contains this request pattern
Update:
Make sure there no console errors and also, if your server application is running on 8081.

Spring Security with HTTPS on CloudFoundry

I tried to access my application on CloudFoundry with the following configuration in the spring security xml
<intercept-url pattern="/signup*" access="permitAll" requires-channel="https" />
but it gives me error This webpage has a redirect loop
However when I changed it to requires-channel="http" I can see my page normally. In both cases I used https on my application. Is this the expected behavior ?
First of all, taking a step back, this (https://johnpfield.wordpress.com/2014/09/10/configuring-ssltls-for-cloud-foundry/) provides excellent context for the nature of the problem.
The key paragraph being
“The threat model here is that the entry point to the cloud is a high availability, secured proxy server.  Once the traffic traverses that perimeter, it is on a trusted subnet.  In fact, the actual  IP address and port number where the Tomcat application server are running are not visible from outside of the cloud. The only way to get an HTTP request to that port is to go via the secure proxy. This pattern is a well established best practice amongst security architecture practitioners.”
Therefore, we may not want or need SSL all the way down, but read on to see how to avoid the https redirect issue when using Spring Security deployed on Cloud Foundry.
You will have a load balancer, HAProxy or some kind of proxy terminating SSL at the boundary of your Cloud Foundry installation. As a convention, whatever you are using should be configured to set X-Forwarded-For and X-Forwarded-Proto headers. The request header “X-Forwarded-Proto" contains the value http or https depending on the original request and you need to use this header parameter for your security decisions further down the stack.
The cleanest way to do this is at the container level, so that Spring Security behaves the same independent of deployment container. Some typical options to configure this are as follows
1) Tomcat
Tomcat should be configured with a RemoteIPValve as described nicely here
The good news is that the Java buildpack for Cloud Foundry already does this for you as seen here
2) Spring Boot (Embedded Tomcat)
Because Tomcat is embedded, the Tomcat config in the Java buildpack will not be activated (see the buildpack Detection Criterion), and therefore some internal Spring Boot configuration is required. Luckily, it’s pretty trivial to configure as you would expect with Spring Boot and you can switch on Tomcat’s RemoteIPValve as explained here by simply defining
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
Both approaches lead to the same outcome of the Tomcat valve overriding the ServletRequest.isSecure() behaviour so that the application has no knowledge of the usage of any proxying. Note that the valve will only be used when the “X-Forwarded-Proto" header is set.
Alternatively, if you really want to go low-level you can dig into the guts of Spring Security, as demonstrated here. As part of that effort, there are some useful findings on how to make the “X-Forwarded-Proto" header available via the Servlet API for other containers (WebLogic, JBoss, Jetty, Glassfish) shared on the comments of https://github.com/BroadleafCommerce/BroadleafCommerce/issues/424
As an additional note, CloudFlare can also act as the SSL-terminating reverse proxy (this is the recommended approach via PWS as discussed here) and it does indeed forward the relevant headers.
References
https://stackoverflow.com/a/28300485/752167
http://experts.hybris.com/answers/33612/view.html
https://github.com/cloudfoundry/java-buildpack/commit/540633bc932299ef4335fde16d4069349c66062e
https://support.run.pivotal.io/entries/24898367-Spring-security-with-https
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html#howto-use-tomcat-behind-a-proxy-server
I have the same issue when I tried to secure my pages with HTTPS using Spring Security.
From the discussion on CloudFoundry Support, seems they "terminate SSL connections at the router". See "Is it possible to visit my application via SSL (HTTPS)?".
And after more than a year, no further information I can find regarding this issue.
In case it's still useful ... I found this post gave the clue to solve something similar to this.
The problem was the org.springframework.security.web.access.channel.SecureChannelProcessor bean was using ServletRequest.isSecure() to decide whether to accept the connection or redirect, which was getting confused inside the cloud.
The following override to that bean seemed to do the job under BlueMix - not sure if the $WSSC request header will apply to all environments.
#Component
public class ChannelProcessorsPostProcessor implements BeanPostProcessor {
#Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
if (bean instanceof SecureChannelProcessor) {
final SecureChannelProcessor scp = (SecureChannelProcessor) bean;
return new ChannelProcessor() {
#Override
public void decide(FilterInvocation invocation,
Collection<ConfigAttribute> config) throws IOException,
ServletException {
HttpServletRequest httpRequest = invocation.getHttpRequest();
// Running under BlueMix (CloudFoundry in general?), the
// invocation.getHttpRequest().isSecure() in SecureChannelProcessor
// was always returning false
if ("https".equals(httpRequest.getHeader("$WSSC"))) {
return;
}
scp.decide(invocation, config);
}
#Override
public boolean supports(ConfigAttribute attribute) {
return scp.supports(attribute);
}
};
}
return bean;
}
#Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
return bean;
}
}

Resources