I've read a lot about switching between multiple datasource on runtime, but as far as I understand they're already defined datasources. I'm not quite sure on how can I just asign the datasources properties on runtime from a webservice call.
I don't need to switch between datasources, just need to create only one datasource with conection data coming from a webservice.
Is there a way to retrieve these parameters from the webservice and create the datasource from that?
The policy here is to retrieve the datasource parameters from a webservice for all the projects, that way the connection data is not inside a file nor into the code, and is only manipulated by DBAs from a global security aplication.
I tried to call the web service in the same datasource file, but it didn't work.
Info:
Web service is a Soap Web service
Grails: 1.3.9
Regards.
I think that you can create a BeanPostProcessor that take care of calling your webservice and changing the settings of your dataSource.
Probably you will need to delay the session factory creation, making sure Grails won't try to use your dataSource before you have all setted up correctly.
The BeanPostProcessor will looks like:
class WebserviceDataSourceBeanPostProcessor implements BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean
}
Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof DataSource){
def info = //call webservice here...
bean.username = info.username
bean.password = info.password
bean.url = info.url
//checkout more setters in: http://commons.apache.org/proper/commons-dbcp/apidocs/org/apache/commons/dbcp/BasicDataSource.html
}
return bean
}
}
And make sure you declared this Spring Bean in resources.groovy
beans = {
webserviceDataSourceBeanPostProcessor(WebserviceDataSourceBeanPostProcessor)
}
If you will have more than one project with this same config comming from a webservice you may think in the possibility of a plugin for this, reusing your code.
Related
I'm writing some functional tests in play, however I want to test my stack isolated from other http endpoints.
Is there a mechanism for me to say "Direct WS calls to this set of canned responses" or some other way of stubbing out calls to http endpoints that won't be available for automated tests?
Alternatively, how does fakeApplication config get presented to the rest of the application so I can just set the URL to some localhost server which I'll build myself to provide canned responses
You could create a structural type that mimics the WS signature and use that in your code.
type WSLike = {
def url(url: String): WSRequestHolder
}
Then you can inject your own version of a WSLike class. In combination with a mock library I guess you could do about anything you want.
As for the second question. You could call it like this:
val url = Play.current.configuration
.getString("my.webservice.url")
.getOrElse(throw new PlayException(
"Configuration error",
"Could not find my.webservice.url in settings"))
WS.url(url)
Then in your application.conf add the correct url. You can supply a different one using the FakeApplication.
FakeApplication(additionalConfiguration =
Map("my.webservice.url" -> "http://localhost/service"))
I am trying to set some session information in one web method and return it in another web method, but the session data is always empty on the second web method. Here is what I tried
Web Method 1 - Sets session information
Method StartSession() As %String [WebMethod]
{
set %session.NewSession = 1
set %session.Data("key") = "dude"
Quit "Session Started"
}
Web Method 2 - Gets session information should return dude, but is returning blank
Method TestSession() As %String [WebMethod]
{
Quit $Get(%session.Data("key"))
}
To use sessions with Cache web services you need to set the SOAPSESSION class parameter of your web service class equal to 1.
Doing so will cause the web service to return a SOAP session header in the response. If you are using a client that was built to expect this header you may not need to set up anything else. Otherwise, your client application will have to read this header and include it in all further requests, so the server can know which session you are using. An example of this header given in the documentation is:
<csp:CSPCHD xmlns:csp="http://www.intersystems.com/SOAPheaders">value of
CPSCHD token</csp:CSPCHD>
Note that security is a separate issue that your example doesn't address.
Also note that Intersystems has decided that web services will continue to use a license for some period of time after the call has been made. I can't find documentation on this, and I believe it's something like a few seconds per call. I believe that this can cause license issues that would not occur if you used other software to provide web services, and had that other software call Cache via some mechanism other than web services. I believe this is true even when that other software carefully follows all the rules in the license agreement about named and anonymous users. However, I'm not certain about any of this licensing stuff. Still, you might want to do some testing before you commit to an architecture.
As an alternative to psr's answer another way to handle state is to use custom SOAP headers.
For example:
Create a class for your custom SOAP headers like below:
Class Headers.TimeStamp Extends %SOAP.Header
{
Property TimeSent As %TimeStamp;
}
In the web method do this:
set h=##class(Headers.TimeStamp).%New()
set h.TimeSent=$ZTIMESTAMP
do ..HeadersOut.SetAt(h,"Timestamp")
This will generate the following SOAP header:
<SOAP-ENV:Header>
<TimeStamp xmlns:hdr="http://www.myapp.org">
<TimeSent>60712,70996.027Z</TimeSent>
</TimeStamp>
</SOAP-ENV:Header>
This will allow state to be maintained within the SOAP headers rather than using Cache's session management.
I use an IOC container which provides me with IService.
In the case where IService is a WCF service it is provided by a channel factory
When IService lives on the same machine it is able to access the same cookies and so no problem however once a WCF Service is called it needs to be sent those cookies.
I've spent a lot of time trying to find a way to send cookies using a channel factory and the only way I could find that works is the following
var cookie = _authenticationClient.GetHttpCookie();
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, cookie.Name + "=" + cookie.Value);
using(var scope = new OperationContextScope((IClientChannel)_service))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
var result = _service.Add(details);
if (result.Result == RPGResult.Success)
{
return RedirectToAction("Index", "Home", result.Id);
}
}
The problem with me using that method is that I have to know that I'm calling a WCF Service which is not always the case. I've tried writing a wrapper for the ChannelFactory that opens a new operationcontextscope when it creates a new service and various other solutions but nothing has worked.
Anyone have any experience with sending cookies over WCF Services?
I found a solution involving using SilverLight, unfortunately I'm not using silverlight, the solution is here: http://greenicicleblog.com/2009/10/27/using-the-silverlight-httpclient-in-wcf-and-still-passing-cookies/
Unfortunately standard .net doesn't contain the IHttpCookieContainerManager interface
Ideally I would be able to use something similar,i.e. I would be able to tell the channelfactory to pass a cookie whenever it opened.
If anyone has a better way to pass a token that is used for authentication that would be appreciated too.
I have a solution where I create a proxy class of IService and then every time a method on IService is called it invokes the proxy created by the channel factory but the call itself is wrapped in an operationcontextscope just like the one I have in my question.
I used the proxy factory from this link http://www.codeproject.com/KB/cs/dynamicproxy.aspx
I just wrote my first web service so lets make the assumption that my web service knowlege is non existant. I want to try to call a dbClass function from the web service. However I need some params that are in the session. Is there any way I can get these call these session variables from the webservice??
If you are using ASP.NET web services and you want to have a session environment maintained for you, you need to embellish your web service method with an attribute that indicates you require a session.
[WebMethod(EnableSession = true)]
public void MyWebService()
{
Foo foo;
Session["MyObjectName"] = new Foo();
foo = Session["MyObjectName"] as Foo;
}
Once you have done this, you may access session objects similar to aspx.
Metro.
You should avoid increasing the complexity of the service layer adding session variables. As someone previously pointed out, think of the web services as isolated methods that take all what is needed to perform the task from their argument list.
In general web services should not rely on session data. Think of them as ordinary methods: parameters go in and an answer comes out.
if you have to want Session["username"].ToString(); as in the other C# pages behind aspx then you should simply replace [WebMethod] above the WebService method with [WebMethod(EnableSession = true)]
thanks to :) Metro
Maybe this will work HttpContext.Current.Session["Name]
Or else you might have to take in some parameters or store them in a Database
Your question is a little vague, but I'll try my best to answer.
I'm assuming that your session variables exist on the server that is making the webservice call, and not on the server that hosts the webservice. In that case, you will need to pass the necessary values as parameters of your web service methods.
To use session in webservice we have to follow 2 steps-
Use [WebMethod(EnableSession = true)] attribute on the method.
Session["Name"] =50 (what ever you want to save)
Please check the following Example.
[WebMethod(EnableSession = true)]
public void saveName(string pname)
{
Session["Name"] = pname;
}
I'm trying to built a SharePoint Web Part that has as part of it a service reference to Another SharePoint server that I need to call from within vb code. However when I try to call the remote web service for the first time, I get the following in the log:
Could not find default endpoint element that references contract 'ListReference.ListsSoap' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element. at System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint, String configurationName)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName)
at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address)
at System.ServiceModel.ChannelFactory1..ctor(String endpointConfigurationName, EndpointAddress remoteAddress)
at System.ServiceModel.EndpointTrait1.CreateSimplexFactory()
at System.ServiceModel.ClientBase1.CreateChannelFactoryRef(EndpointTrait1 endpointTrait)
at System.ServiceModel.ClientBase1.InitializeChannelFactoryRef()
at System.ServiceModel.ClientBase1..ctor()
at VSeWSS.ChangeRequestWorkflow.ChangeRequest.SubmitForm(Object sender, EventArgs e)
What is the proper way to deploy a Web Part with a Service Reference, could I be doing something wrong? Thanks!
You need to add the endpoint configuration into the web.config of the SharePoint site that is consuming the webservice.
I found this question that solved my problem.
Basically, I just needed to create a BasicHttpBinding object and populate its properties with the ones the SVC generator made in my app.config.
WCF Configuration without a config file
Actually I solved my problem. My application has many projects, and the config file was in the project calling the WebService, but it seems it has to be in the starting project...
Hm, if I'm understanding what you're asking correctly, I'm doing that. I just added the webservice from one of the correct endpoints to the project in VS, then before I call it in my actual code, I get the URL I want to connect to with this call from the hierarchical object store from Codeplex, then set the Url property. So:
MyService srv = new MyService();
srv.Url = SPContext.Current.Web.Properties["serviceurl"];
Its working like that fine.
hth.