I have an application that is running on a Java EE 7 application server (WildFly), that queries another service using REST resources.
In previous applications I have used the Jersey 1.x client API. Access to the REST service is granted through a web proxy.
In Jersey I create the Client instance like this:
public Client create() {
Client client;
if ( proxyConfiguration != null && proxyConfiguration.getHost() != null && !proxyConfiguration.getHost().trim().isEmpty() ) {
HttpURLConnectionFactory urlConnectionFactory = new ProxyUrlConnectionFactory( proxyConfiguration );
client = new Client( new URLConnectionClientHandler( urlConnectionFactory ), clientConfig );
} else {
client = Client.create( clientConfig );
}
return client;
}
Running on a Java EE 7 application server I wanted to use the JAX-RS 2.0 client API which is provided by the application server.
Now I am having a really hard time to find information on how to configure the JAX-RS 2.0 client in a platform independent way. Setting the http.proxyHost and http.proxyPort system properties had no effect in WildFly (I would prefer to not configure it globally anyway).
Does anyone know how to solve this?
I think there's no vendor independent solution (at least, I didn't find anything related to proxies in the JAX-RS API).
For Jersey 2.x, you can try:
ClientConfig config = new ClientConfig();
config.property(ClientProperties.PROXY_URI, "192.168.1.254:8080");
Client client = ClientBuilder.withConfig(config).build();
ClientProperties is a class from Jersey API.
For RESTEasy, the configuration is:
Client client = new ResteasyClientBuilder()
.defaultProxy("192.168.1.254", 8080, "http")
.build();
ResteasyClientBuilder is a class from RESTEasy API.
With (WildFly and) RESTEasy (6.2.1.Final) set a proxy with:
final Client client = ClientBuilder.newBuilder()
.property("org.jboss.resteasy.jaxrs.client.proxy.host", "192.168.1.254")
.property("org.jboss.resteasy.jaxrs.client.proxy.port", 8080)
.build();
See Jakarta RESTFul Web Services: 51.3.3. HTTP proxy.
Related
I'm very new to WCF SOAP.
Having successfully built a basic REST( web api) web service and tested it through a url (eg a GET on api/users/1 to return a user with id = 1 from database), I'm now attempting something similar with a WCF SOAP web service.
I don't want to build a proxy client. Ideally i'd like to just test within browser or using Fiddler.
Here's the ABC (Address, Binding, Contract) program.cs code:
static void Main(string[] args)
{
// Step 1 Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:1234/WCFsoap");
// Step 2 : Create ServiceHost (this will host the webservice)
ServiceHost selfHost = new ServiceHost(typeof(UserLookupWebService), baseAddress);
try
{
// Step 3 : Add a service endpoint.
selfHost.AddServiceEndpoint(
typeof(IUserLookup), //Contract
new BasicHttpBinding(), //Binding
"newapi"); //Address (relative to selfhost url)
For example:
How would I call a findUser(int userId = 1) method within a UserLookupWebService class? And can i do this from a browser or Fiddler?
You can either create a proxy class using svcutil.exe and use that class to connect to your service:
svcutil http://localhost:1234/WCFsoap
Or use any SOAP test tool out there:
I really like Soap UI but you can use as well WCF Test client for example
Does anyone know the trick to calling a WCF (Soap 1.2) web service from CXF?
I've been trying to get a basic hello world client working for a while now and I've had no luck.
It works fine with Soap 1.1.
When I print out the SoapBinding the client is using it's using soap 1.1 even though it's a soap 1.2 service
when I set the soap binding manually to 1.2 it freezes up when you make the web service call and eventually dies with a socket timeout exception (Read timed out).
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ITest.class);
factory.setAddress("http://localhost/Test/test.svc");
final Soap12 soap12 = Soap12.getInstance();
BindingConfiguration config = new BindingConfiguration() {
#Override
public String getBindingId() {
return soap12.getBindingId();
}
};
factory.setBindingConfig(config);
factory.setBindingId(soap12.getBindingId());
ITest service = (ITest) factory.create();
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(service);
client.getRequestContext().put("ContentType", "text/xml; charset=utf-8");
SoapBinding binding = (SoapBinding) client.getEndpoint().getBinding();
System.out.println("[" + binding.getSoapVersion() + "]");
System.out.println(service.test("World"));
}
This is the soap request that gets sent to the WCF Service.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<Test xmlns="http://tempuri.org/" xmlns:ns2="http://schemas.microsoft.com/2003/10/Serialization/">
<s>World</s>
</Test>
</soap:Body>
</soap:Envelope>
I think your major issue with the communication between the WCF and CXF is the lack of ws-addressing headers present on the request. When you enable wsHttpBinding, WCF expects a client that understands ws-addressing. This is a feature of CXF, but needs to be enabled. The following code should resolve your issues:
// add the ws-addressing feature on the proxy factory.
factory.getFeatures().add(new org.apache.cxf.ws.addressing.WSAddressingFeature());
This solution works with CXF 3.x.
I actually found out CXF doesn't support calling a Soap 1.2 WCF Service that uses wsHttpBinding. I switched the WCF web service to use BasicHttpBinding and It works now.
Here's what I've done so far:
1) Created an ASP.NET MVC relying party application and secured it with ADFS v2.0. This works.
2) Created a WCF Service using the Claims-Aware service template for an ASP.NET website. I've turned ASP.NET compatibility for the service ON because the service wouldn't activate otherwise. I've moved the interface for said service to a 'SharedContracts' assembly.
3) Set up the WCF service as a relying party using the "Add STS" reference, also pointing at my ADFS server.
4) Configured the ADFS server to include the WCF service as a relying party and issue it LDAP claims.
What I want to do now is talk to the service using ActAs. In other words, when someone hits HomeController.Index() from the ASP.NET MVC site with a token full of claims (remember the MVC site is a relying party), I want this method to programmatically create a client proxy and invoke the single service method I have on the WCF service (a method called "HelloClaim", which is nearly identical to the stock method that comes with the claims-aware service template).
Here's the code I've got so far:
[ValidateInput(false)]
public ActionResult Index()
{
SecurityToken callerToken = null;
IClaimsPrincipal claimsPrincipal = Thread.CurrentPrincipal as IClaimsPrincipal;
if (claimsPrincipal != null)
{
foreach (IClaimsIdentity claimsIdentity in claimsPrincipal.Identities)
{
if (claimsIdentity.BootstrapToken is SamlSecurityToken)
{
callerToken = claimsIdentity.BootstrapToken;
break;
}
}
string baseAddress = "http://khoffman2/SecureServices/Service.svc";
ChannelFactory<IHelloClaim> factory = new ChannelFactory<IHelloClaim>(new WebHttpBinding(), new EndpointAddress(baseAddress));
factory.ConfigureChannelFactory<IHelloClaim>();
IHelloClaim hello = factory.CreateChannelActingAs<IHelloClaim>(callerToken);
string result = hello.HelloClaim();
ViewData["Message"] = "Welcome to ASP.NET MVC!";
}
return View();
}
When I attempt to invoke the method, I get the following error message:
Manual addressing is enabled on this factory, so all messages sent must be pre-addressed.
I'm pretty sure I'm just not doing enough to configure the binding and the endpoint programmatically. If any of you have done this before or you know how to do it, I would love to be able to get this working.
Bottom line is I'm just making use of the basic identity delegation scenario - the only difference is I'm not using generated client proxies.
Take a look at this guide over at TechNet as it has a walkthrough on how to setup the scenario you've described:
http://technet.microsoft.com/en-us/library/adfs2-identity-delegation-step-by-step-guide(WS.10).aspx
In their example, I believe they are using standard WebForms, but in the case of MVC you can put the ChannelFactory initialization within the Global.asax within the Application_Start.
As the title says, I would like to consume a WF workflow using a ASP.NET 1.1 client.
The workflow is hosted on IIS as a .svc service.
I have a .NET 3.5 winforms test client that uses wsHttpContextBinding.
Because I need to put a WorkflowID in Context to have my workflow rehydrated and continued, I use this piece of code:
var Svc = new MyClient.MyService();
var Ctx = new Dictionary<string, string>();
Ctx.Add("instanceId", workflowID.ToString());
var CtxMgr = Svc.InnerChannel.GetProperty<IContextManager>();
CtxMgr.SetContext(Ctx);
Svc.MyOperation();
It's working fine this way.
Unfortunately, my ASP.NET 1.1 legacy appliction need to consume this workflow. I have setup an additional endpoint that uses basicHttpContextBinding.
I have read the context has to be passed to a cookie, and I'm stuck here as I have no clue about how to do this in the caller code.
MyClient.MyService Svc= new MyClient.MyService();
// How to set the workflowID ?
Svc.MyOperation();
How can I set the context with a workflowID in the cookie ?
Apparently, there is no miracle nor solution. The workflowID has to be handled to the client side, which concerns me because the client is not aware about the server plumbing.
How can I set the HTTP proxy programmatically, on a WCF client, without using the default proxy?
Proxies, proxies, proxies.
According to the WCF model of development, I generate client-side "proxy"
classes by running svcutil.exe on the WSDL for the service. (This also
produces a client-side config file).
In my code I new-up an instance of that class and I can connect to the
service. Very nice.
var svcProxy = new MyWebService();
svcProxy.GetInformation(request);
We call this thing a proxy class, but there is another proxy - the http proxy. This
service is using wsHttpBinding basicHttpBinding, so it is going over
http. Now, suppose I want to connect the client to the web service over
a http proxy (modeled by a System.Net.WebProxy in the .NET BCL). I know
from my extensive, delightful experience reading .NET and WCF documentation, that
the WCF runtime, if not instructed otherwise, will use the default
system proxy when communicating over http/https.
I can set that from the command line in
WinXP / 2003 with ProxyCfg.exe as described here, and in later
versions of Windows with netsh.exe as described here.
I can also specify the default web proxy for use within the application
by setting the System.Net.WebRequest.DefaultWebProxy property.
But suppose I want to connect over a proxy that is different than the
system-wide proxy? For instance maybe there is no system-wide proxy but
I need to use one for the web service in particular. Or maybe there is
a system-wide proxy but I need to use a different one, for the web
service. And in fact maybe there are multiple web service clients, and
each one should get a different proxy.
How can the proxy be set per-binding?
In the ASMX model, I could do this:
var svcProxy = new MyWebService();
svcProxy.Proxy = new System.Net.WebProxy("http://proxyserver:1234", true);
svcProxy.GetInformation(request);
But this is not possible with WCF; the WCF-generated client-side proxy
classes do not expose a Proxy property. How do I set the http proxy, per client-side proxy, and how do I set authentication on the http proxy as well?
Related:
- how-to-set-proxy-with-credentials-to-generated-wcf-client
It makes sense that there is no Proxy property on the WCF proxy, because not all WCF proxies use HTTP for communication. After further review, I found that it is possible to set the proxy in WCF programmatically, if the WCF proxy uses an HTTP binding. I am documenting it here in case someone else needs it. To set the HTTP Proxy in code for a WCF client, do this:
// instantiate a proxy for the service
var svc= new ServiceClient();
// get the HTTP binding
var b = svc.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
b.ProxyAddress = new Uri("http://127.0.0.1:8888");
b.BypassProxyOnLocal = false;
b.UseDefaultWebProxy = false;
And to set the endpoint address - where to reach the server - in code, you would do something like this:
var e = svc.Endpoint;
e.Address = new System.ServiceModel.EndpointAddress(
"http://remoteserver:5555/WcfXmlElement");
The proxy settings are part of the binding configuration. For example, look at the ProxyAddress property of the BasicHTTPBinding and WSHttpBinding classes/configuration elements.
Looks like you're leaving your endpoint configuration in the app.config file, in which case you should be able to set the address there.
I have had a similar problem, but I also needed to use a username and password for the proxy that differ from the username and password used to access the service.
I tried building it up through a UriBuilder, which would output the proxy address as "http://username:password#myproxyserver/". Unfortunately, the particular proxy I was using didn't work with this technique.
What I found after extensive Googling, is that you can change the proxy through WebRequest.DefaultProxy (static property).
For example:
WebProxy proxy = new WebProxy("http://myproxyserver",true);
proxy.Credentials = new NetworkCredential("username", "password");
WebRequest.DefaultWebProxy = proxy;
You could also try this :
Programmatically get whatever binding you are using,and then set the proxy on it directly e.g.
var binding = new WSDualHttpBinding("WSDualHttpBinding_IMainService");
binding.ProxyAddress = new Uri("http://192.168.5.1:3128");
where "WSDualHttpBinding_IMainService" is the name of your binding from your config file.
Also you have to set UseDefaultWebProxy=false; otherwise your proxy will be ignored.
I found a solution for someone who might use .NET Core 2.x
Which initially cause an issue when trying to set proxy by using
System.ServiceModel.BasicHttpBinding;
as answered by Cheeso.
You have to update WCF to the latest (v.4.7.0).
Go to NuGet Package Manager -> Update all related Project URL of WCF.
There must be:
System.ServiceModel.Security
System.ServiceModel.NetTcp
System.ServiceModel.Http