I often use webservice this way
public void CallWebservice()
{
mywebservice web = new mywebservice();
web.call();
}
but sometimes I do this
private mywebservice web;
public Constructor()
{
web = new mywebservice();
}
public void CallWebservice()
{
web.call();
}
The second approach likes me very much but sometimes it times out and I had to start the application again, the first one I think it brings overhead and it is not very efficient, in fact, sometimes the first call returns a WebException - ConnectFailure (I don't know why).
I found an article (Web Service Woes (A light at the end of the tunnel?)) that exceeds the time out turning the KeepAlive property to false in the overriden function GetWebRequest, here's is the code:
Protected Overrides Function GetWebRequest(ByVal uri As System.Uri) As System.Net.WebRequest
Dim webRequest As Net.HttpWebRequest = CType(MyBase.GetWebRequest(uri), Net.HttpWebRequest)
webRequest.KeepAlive = False
Return webRequest
End Function
The question is, is it possible to extend forever the webservice time out and finally, how do you implement your webservices to handle this issue?
The classes generated by Visual Studio for webservices are just proxies with little state so creating them is pretty cheap. I wouldn't worry about memory consumption for them.
If what you are looking for is a way to call the webmethod in one line you can simply do this:
new mywebservice().call()
Cheers
Related
Trying to write some proper AEM integration tests using the aem-mocks framework. The goal is to try and test a servlet by calling its path,
E.g. an AEM servlet
#SlingServlet(
paths = {"/bin/utils/emailSignUp"},
methods = {"POST"},
selectors = {"form"}
)
public class EmailSignUpFormServlet extends SlingAllMethodsServlet {
#Reference
SubmissionAgent submissionAgent;
#Reference
XSSFilter xssFilter;
public EmailSignUpFormServlet(){
}
public EmailSignUpFormServlet(SubmissionAgent submissionAgent, XSSFilter xssFilter) {
this.submissionAgent = submissionAgent;
this.xssFilter = xssFilter;
}
#Override
public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
String email = request.getParameter("email");
submissionAgent.saveForm(xssFilter.filter(email));
}
}
Here is the corresponding test to try and do the integration testing. Notice how I've called the servlet's 'doPost' method, instead of 'POST'ing via some API.
public class EmailSignUpFormServletTest {
#Rule
public final AemContext context = new AemContext();
#Mock
SubmissionAgent submissionAgent;
#Mock
XSSFilter xssFilter;
private EmailSignUpFormServlet emailSignUpFormServlet;
#Before
public void setup(){
MockitoAnnotations.initMocks(this);
Map<String,String> report = new HashMap<>();
report.put("statusCode","302");
when(submissionAgent.saveForm(any(String.class)).thenReturn(report);
}
#Test
public void emailSignUpFormDoesNotRequireRecaptchaChallenge() throws IOException {
// Setup test email value
context.request().setQueryString("email=test.only#mail.com");
//===================================================================
/*
* WHAT I END UP DOING:
*/
// instantiate a new class of the servlet
emailSignUpFormServlet = new EmailSignUpFormServlet(submissionAgent, xssFilter);
// call the post method (Simulate the POST call)
emailSignUpFormServlet.doPost(context.request(),context.response());
/*
* WHAT I WOULD LIKE TO DO:
*/
// send request using some API that allows me to do post to the framework
// Example:
// context.request().POST("/bin/utils/emailSignUp") <--- doesn't exist!
//===================================================================
// assert response is internally redirected, hence expected status is a 302
assertEquals(302,context.response().getStatus());
}
}
I've done a lot of research on how this could be done (here) and (here), and these links show a lot about how you can set various parameters for context.request() object. However, they just don't show how to finally execute the 'post' call.
What you are trying to do is mix a UT with IT so this won't be easy at least with the aem-mocks framework. Let me explain why.
Assuming that you are able to call your required code
/*
* WHAT I WOULD LIKE TO DO:
*/
// send request using some API that allows me to do post to the framework
// Example:
// context.request().POST("/bin/utils/emailSignUp") <--- doesn't exist!
//===================================================================
Your test will end up executing all the logic in SlingAllMethodsServlet class and its parent classes. I am assuming that this is not what you want to test as these classes are not part of your logic and they already have other UT/IT (under respective Apache projects) to cater for testing requirements.
Also, looking at your code, bulk of your core logic resides in following snipper
String email = request.getParameter("email");
submissionAgent.saveForm(xssFilter.filter(email));
Your UT criteria is already met by the following line of your code:
emailSignUpFormServlet.doPost(context.request(),context.response());
as it covers most of that logic.
Now, if you are looking for proper IT for posting the parameters and parsing them all the way down to doPost method then aem-mocks is not the framework for that because it does not provide it in a simple way.
You can, in theory, mock all the layers from resource resolver, resource provider and sling servlet executors to pass the parameters all the way to your core logic. This can work but it won't benefit your cause because:
Most of the code is already tested via other UT
Too many internal mocking dependencies might make the tests flaky or version dependant.
If you really want to do pure IT, then it will be easier to host the servlet in an instance and access it via HttpClient. This will ensure that all the layers are hit. A lot of tests are done this way but it feels a bit heavy handed for the functionality you want to test and there are better ways of doing it.
Also the reason why context.request().POST doesn't exist is because context.request() for is a mocked state for the sake of testing. You want to actually bind and mock Http.Post operations which needs some way to resolve to your servlet and that is not supported by the framework.
Hope this helps.
I have a web service with an operation that looks like
public Result checkout(String id) throws LockException;
implemented as:
#Transactional
public Result checkout(String id) throws LockException {
someDao.acquireLock(id); // ConstraintViolationException might be thrown on commit
Data data = otherDao.find(id);
return convert(data);
}
My problem is that locking can only fail on transaction commit which occurs outside of my service method so I have no opportunity to translate the ConstraintViolationException to my custom LockException.
Option 1
One option that's been suggested is to make the service delegate to another method that's #Transactional. E.g.
public Result checkout(String id) throws LockException {
try {
return someInternalService.checkout(id);
}
catch (ConstraintViolationException ex) {
throw new LockException();
}
}
...
public class SomeInternalService {
#Transactional
public Result checkout(String id) {
someDao.acquireLock(id);
Data data = otherDao.find(id);
return convert(data);
}
}
My issues with this are:
There is no reasonable name for the internal service that isn't already in use by the external service since they are essentially doing the same thing. This seems like an indicator of bad design.
If I want to reuse someInternalService.checkout in another place, the contract for that is wrong because whatever uses it can get a ConstraintViolationException.
Option 2
I thought of maybe using AOP to put advice around the service that translates the exception. This seems wrong to me though because checkout needs to declare that it throws LockException for clients to use it, but the actual service will never throw this and it will instead be thrown by the advice. There's nothing to prevent someone in the future from removing throws LockException from the interface because it appear to be incorrect.
Also, this way is harder to test. I can't write a JUnit test that verifies an exception is thrown without creating a spring context and using AOP during the tests.
Option 3
Use manual transaction management in checkout? I don't really like this because everything else in the application is using the declarative style.
Does anyone know the correct way to handle this situation?
There's no one correct way.
A couple more options for you:
Make the DAO transactional - that's not great, but can work
Create a wrapping service - called Facade - whose job it is to do exception handling/wrapping around the transactional services you've mentioned - this is a clear separation of concerns and can share method names with the real lower-level service
I register components in global.asax.I resolve in try block in every web method and release in finally block. I created a wrapper for container so that it is called directly only during registration. Web methods call this wrapper to resolve and release components. This try finally adds a lot of boilerplate code.
Am I doing right? If not how should I do it? I am using Castle Windsor.
[WebMethod]
public void SomeMethod()
{
ISomeComponent c = null
try
{
c = myContainer.ResolveSomeComponent();
c.Method();
}
finally
{
myContainer.Release(c);
}
}
I have found the solution. As it turns out I can configure my components as Per Web Request and then I don't have to release them because they will be automatically released at the end of request.
You can find details in this article: http://devlicio.us/blogs/krzysztof_kozmic/archive/2010/08/27/must-i-release-everything-when-using-windsor.aspx
I'm considering my options for setting up a class for unit testing. This particular class should ALWAYS use the same soap client configuration under normal circumstances. I feel like users of the class shouldn't need to be concerned with setting up a soap client when they use it. Or, even be aware that it uses soap at all.
Really the only exception is in unit testing. I'll need to be able to mock the Soap_Client. I've come up with the following approach where i create the soap client in the constructor and can optionally set it with setSoapClient().
class WebServiceLayer
{
const WSDL_URL = 'https://www.example.com/?WSDL';
private $soapClient;
public function __construct()
{
$this->soapClient = new Soap_Client(self::WSDL_URL);
}
public function setSoapClient(Soap_Client $soapClient)
{
$this->soapClient = $soapClient;
}
public function fetchSomeResponse()
{
$soapClient = $this->soapClient;
return $soapClient->someRequest();
}
}
Is this a valid way to handle this? The only problem i see with it, is that im instantiating the client in the constructor which "i've heard" is something to avoid.
I've run into this dilemma before on other classes, so it would be really nice to get peoples opinions on this.
Looks fine to me... you're using standard Setter injection. The only strange thing is returning a new client in the Getter. Why not return null if it hasn't been injected?
I have the following method:
private string _google = #"http://www.google.com";
public ConnectionStatus CheckCommunicationLink()
{
//Test if we can get to Google (A happy website that should always be there).
Uri googleURI = new Uri(_google);
if (!IsUrlReachable(googleURI, mGoogleTestString))
{
//The internet is not reachable. No connection is available.
return ConnectionStatus.NotConnected;
}
return ConnectionStatus.Connected;
}
The question is, how do I get it to not try the connection to Google (thus avoiding the dependency on the internet being up).
The easiest way is to take _google and change it to point to something local to the machine. But to do that I need to make _google public. I would rather not do that because _google should not ever be changed by the app.
I could make `_google' a param to an overloaded version of the method (or object constructor). But that too exposes an interface that I don't ever want the app to use.
The other option is to make _google internal. But for the app, internal is the same as public. So, while others cannot see _google, the app interface still exposes it.
Is there a better way? If so, please state it.
(Also, please don't pick on my example unless it really helps figure out a solution. I am asking for ideas on general scenarios like this, not necessarily this exact example.)
Refactor your code to depend on an ICommunicationChecker:
public interface ICommunicationChecker
{
ConnectionStatus GetConnectionStatus();
}
Then your test(s) can mock this interface making the implementation details irrelevant.
public class CommunicationChecker : ICommunicationChecker
{
private string _google = #"http://www.google.com";
public ConnectionStatus GetConnectionStatus()
{
//Test if we can get to Google (A happy website that should always be there).
Uri googleURI = new Uri(_google);
if (!IsUrlReachable(googleURI, mGoogleTestString))
{
//The internet is not reachable. No connection is available.
return ConnectionStatus.NotConnected;
}
return ConnectionStatus.Connected;
}
}
Why do you have _google hard coded in your code? Why not put it in a configuration file which you can then change for your test for example?
Some options:
make _google load from an external configuration (maybe providing www.google.com as a default value) and supply a special configuration for unit tests;
place the unit test class inside the class containing the CheckCommunicationLink method.
Note: I would strongly recommend making it configurable. In real-world cases relying on the availability of a particular 3rd party web site is not a good idea, because they can be blocked by a local firewall etc.
For unit testing purposes you should mock whatever http connection you are using in your class (which is hidden in IsUrlReachable method). This way you can check that your code is really trying to connect to google without actually connecting. Please paste the IsUrlReachable method if you need more help with mocking.
If the above solution is not an option, you could consider having a local test http server and:
Making the url configurable, so that you can point to the local address
(this one is nasty) Use reflection to change _google before the tests
(most purist will disagree here) You could create an overload taking the parameter and use this one for testing (so you test only CheckCommunicationLink(string url) method
code for (3):
private string _google = #"http://www.google.com";
public ConnectionStatus CheckCommunicationLink()
{
return CheckCommunicationLink(_google);
}
public ConnectionStatus CheckCommunicationLink(string url)
{
//Test if we can get to Google (A happy website that should always be there).
Uri googleURI = new Uri(url);
if (!IsUrlReachable(googleURI, mGoogleTestString))
{
//The internet is not reachable. No connection is available.
return ConnectionStatus.NotConnected;
}
return ConnectionStatus.Connected;
}