I'm trying to automate a call so that when a user calls a Twilio number, the code will generate XML and send it as an HTTP response to the caller. The example on their webpage goes:
#SuppressWarnings("serial")
#WebServlet("/voice")
public class IncomingCallServlet extends HttpServlet {
// Handle HTTP POST to /voice
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Create a TwiML builder object
VoiceResponse twiml = new VoiceResponse.Builder()
.say(new Say.Builder("Hello world!")
.voice(Say.Voice.ALICE)
.build())
.build();
// Render TwiML as XML
response.setContentType("text/xml");
try {
response.getWriter().print(twiml.toXml());
} catch (TwiMLException e) {
e.printStackTrace();
}
}
}
But how do I get this to run since there's no main method? I'm using spark to run it on a local port then creating a webhook to the application using ngrok. It works if I have a main, but the example here doesn't give any.
Any suggestion on how I'd get this code to run and generate the XML.
Funny thing is, I don't see any reference to Spark in your code, and it could run on any Java Web container, provided that you declare the servlet in a well formed web.xml. If I understand your question and code extract correctly, you seem to be willing to rely upon the Jetty server embedded into Spark to load this servlet.
If you want to leverage Spark and avoid the hassle of explicitly declaring your servlet, you could write something like this (assuming you're running Java 8):
import com.twilio.twiml.Say;
import com.twilio.twiml.VoiceResponse;
import static spark.Spark.*
public class IncomingCall {
public static void main(String[] args) {
// You might want to pass the listen port
// e.g as CLI argument or system property
port(4567);
post("/voice", (request, response) -> {
// Create a TwiML builder object
VoiceResponse twiml = new VoiceResponse.Builder()
.say(new Say.Builder("Hello world!")
.voice(Say.Voice.ALICE)
.build())
.build();
// Render TwiML as XML
response.type("text/xml");
try {
return twiml.toXml();
} catch (TwiMLException e) {
// This will result in a HTTP 500
throw new RuntimeException(e);
}
}
}
}
It's possible to implement SparkApplication interface, declare a filter in your web.xml and run it in another web server according to the documentation.
Related
At the moment my website is using Spring that handles the http(s) request to and from the front-end like this:
#RestController
public class ComputeController {
#RequestMapping(value = "/api/compute", method = RequestMethod.POST)
public String compute(#RequestBody CodeToken code, OAuth2Authentication OAuth2) {
Map<String, String> userInfo = UserInformation.getUserInfo(OAuth2);
String sourceCode = code.getSource();
String filename = code.getFilename();
String email = userInfo.get("email");
try {
DataStorage dateStorage = new DataStorage();
Compiler compiler = new Compiler(dateStorage);
return compiler.compile(filename, sourceCode, email);
} catch (Exception e) { // TODO Don't catch all exceptions
return e.getStackTrace().toString();
}
}
}
The problem is that I need my front-end (built in Angular) to be able to receive and send information asynchronous from the http(s) request sent from the front-end. Like an continuous I/O stream from the server mid request while the "compiler.compile(...)" is running.
I presume I need to use sockets for this but I'm looking for suggestion on a good way to implement them.
If I understand your intention correctly, you're trying to display some progress in your client while the code compiles. You have two options:
As you proposed, use WebSockets. Spring supports them well. You can see an example here: https://github.com/AlexeySoshin/SpringWebSockets/tree/master/src/main/java/com/alexeysoshin/chat
Instead of blocking your response,
Do compilation on a separate thread pool.
Assign each compilation UUID when you submit this task.
Return the client this task immediately.
Poll another endpoint with UUID
The SOAP API I am intending to use has given a working example in Java. In every request to the API one should add three values to the header (I just guess they are a domain, a password and api key). To this aim we override the org.apache.axis.client.Stub like this:
public class SeveraApiStubBase extends org.apache.axis.client.Stub {
#Override
public org.apache.axis.client.Call _createCall() throws ServiceException {
org.apache.axis.client.Call _call = super._createCall();
_call.addHeader(new org.apache.axis.message.SOAPHeaderElement(
"http://something.somethingelse.com/", "WebServicePassword", "API_KEY"));
return _call;
}
}
And then we run the method with the provided header.
I was wondering what the equivalent is in C#.
Update: The use of the IClientMessageInspector class
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
if (string.IsNullOrEmpty(httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER]))
{
httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER] = this.m_userAgent;
}
}
else
{
httpRequestMessage = new HttpRequestMessageProperty();
httpRequestMessage.Headers.Add(USER_AGENT_HTTP_HEADER, this.m_userAgent);
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
}
return null;
}
Normally you would use WCF if using C# rather than Axis. It is a little different of an approach than Axis.
Assuming you're making a client consuming an existing WSDL, you would start by using svcutil to generate your service contract code. Here is a link that describes this part. The example they give is a service with primitive inputs to all operations, so it doesn't show generation of complex type classes.
You can then use message inspectors to intercept the outgoing request and add a header. The IClientMessageInspector interface has the method BeforeSendRequest that passes a Message class as an argument. The Message class has a Headers collection where you can add whatever headers you need.
I am creating webservices in Java using RESTlet API. I am using 2.0 stable version.
In this I am getting NullPointerException error while reading the request for second time.
I have applied the Filter on webservices for security purpose. In filter class I am checking the request contains the expected parameters. If it is successful then the call is made to webservice.
While processing in the webservice I am getting the NULL in request. Following is my Filter class -
public class MyFilter extends Filter {
public MyFilter(Context context) {
super(context);
}
#Override
protected int beforeHandle(Request request, Response response) {
int result = STOP;
try
{
String requestSt = request.getEntityAsText();
// Check for validation
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
When I read the request for second time it returns NULL. Even when I just write -
System.out.println(request.getEntityAsText());
before -
String requestSt = request.getEntityAsText();
then also it gives me NullPointerException for the line String requestSt = ....
So please provide me the solution to read the request for multiple times.
You can wrap the incoming request entity to ensure its content isn't lost after reading it a first time. For this purpose, you can leverage the org.restlet.engine.io.BufferingRepresentation class.
This line should do it:
request.setEntity(new BufferingRepresentation(request.getEntity());
You might need to update to version 2.1 which is the current stable version.
I'm using RESTEasy 2.2.1.GA as my JAX-RS implementation to create a client to connect to a third party service provider. (Education.com's REST API if it matters)
To make sure I haven't missed an important implementation detail here are code samples:
Service Interface
#Path("/")
public interface SchoolSearch {
#GET
#Produces({MediaType.APPLICATION_XML})
Collection<SchoolType> getSchoolsByZipCode(#QueryParam("postalcode") int postalCode);
}
Calling Class
public class SimpleSchoolSearch {
public static final String SITE_URL = "http://api.education.com/service/service.php?f=schoolSearch&key=****&sn=sf&v=4";
SchoolSearch service = ProxyFactory.create(SchoolSearch.class, SITE_URL);
public Collection<SchoolType> getSchools() throws Exception {
Collection<SchoolType> schools = new ArrayList<SchoolType>();
Collection<SchoolType> response = service.getSchoolsByZipCode(35803);
schools.addAll(response);
return schools;
}
}
After setting up tests to make this call, I execute and see the following exception being thrown.
org.jboss.resteasy.plugins.providers.jaxb.JAXBUnmarshalException: Unable to find JAXBContext for media type: text/html;charset="UTF-8"
From reading the RESTEasy/JAX-RS documentation, as I understand it, when the response is returned to the client, prior to the unmarshaling of the data, a determination is made (Content Negotiation??) about which mechanism to use for unmarshalling. (I think we're talking about a MessageBodyReader here but I'm unsure.) From looking at the body of the response, I see that what is returned is properly formatted XML, but the content negotiation (via HTTP header content-type is indeed text/html;charset ="UTF-8") is not allowing the text to be parsed by JAXB.
I think that the implementation is behaving correctly, and it is the service that is in error, however, I don't control the service, but would still like to consume it.
So that being said:
Am I correct in my understanding of why the exception is thrown?
How do I work around it?
Is there a simple one line annotation that can force JAXB to unmarshal the data, or will I need to implement a custom MessageBodyReader? (If that is even the correct class to implement).
Thanks!
Follow Up:
I just wanted to post the few changes I made to Eiden's answer. I created a ClientExecutionInterceptor using his code and the information available at Resteasy ClientExecutionInterceptor documentation. My final class looks like
#Provider
#ClientInterceptor
public class SimpleInterceptor implements ClientExecutionInterceptor {
#Override
public ClientResponse execute(ClientExecutionContext ctx) throws Exception {
final ClientResponse response = ctx.proceed();
response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);
return response;
}
}
The big difference is the addition of the #Provider and #ClientExecutionInterceptor annotations. This should insure that the interceptor is properly registered.
Also, just for completeness, I registered the Interceptor slightly differently for my tests. I used:
providerFactory.registerProvider(SimpleInterceptor.class);
I'm sure there are several solutions to this problem, but I can only think of one.
Try so set the content-type using a ClientExecutionInterceptor:
public class Interceptor implements ClientExecutionInterceptor {
#Override
public ClientResponse<?> execute(ClientExecutionContext ctx) throws Exception {
final ClientResponse<?> response = ctx.proceed();
response
.getHeaders()
.putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);
return response;
}
}
public void getSchools() throws Exception {
ResteasyProviderFactory.getInstance()
.getClientExecutionInterceptorRegistry()
.register( new Interceptor() );
SchoolSearch service =
ProxyFactory.create(SchoolSearch.class, SITE_URL);
}
I dont know about any such annotation, others might do, but a workaround is to create a local proxy. Create a controller, that passes all parameters to education.com using a
java.Net.URL.get()
return the answer that you received, but modify the header. Then connect your client to the local proxy controller.
Oh hello there, fellow SO members,
I have a web service that returns XML data using a simple get request that goes like this :
http://my-service:8082/qc/getData?paramX=0169¶mY=2
the service returns raw xml in the page according to the parameters' values.
I am trying to retrieve this data from a GET request in GWT using RequestBuilder, Request, etc.
However, the response gives me empty text, a Status code of ZERO (which doesn't mean anything and isn't supposed to happen), and so on.
Here's the simplified code that doesn't work.
public class SimpleXML implements EntryPoint {
public void onModuleLoad() {
this.doGet("http://my-service:8082/qc/getData", "0169", "2");
}
public void doGet(String serviceURL, String paramX, String paramY) {
final String getUrl = serviceURL + "?paramX=" + paramX + "&idTarification=" + paramY;
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, getUrl);
try {
Request response = builder.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
response.getStatusCode(); // Gives me 0 (zero) :(
}
#Override
public void onError(Request request, Throwable exception) {
// ... doesn't matter for this example
}
});
} catch (RequestException e) {
// ... doesn't matter for this example
}
}
}
I don't get why this wouldn't work, since this is REALLY simple, I've seen tutorials and they all show me this way of doing things..
Thanks in advance
The reason is, that browsers do not allow cross-site requests with AJAX (see Same Origin Policy).
This means, that you can only call a service on the same server, same port (using the same protocol) as your HTML page. If you want to perform cross-site requests, you can use JSONP, as explained in http://code.google.com/webtoolkit/doc/latest/tutorial/Xsite.html.