I need to read data from an xml file that is under the WAR directory.
I'm using RequestBuilder for creating the GET request.
It looks like this:
RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET,"customerRecord.xml");
try {
requestBuilder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
requestFailed(exception);
}
public void onResponseReceived(Request request,Response response) {
renderXML(response.getText());
}
});
} catch (RequestException ex) {
requestFailed(ex);
}
Now, the thing is that I don't want to load all of the data. I want to send a parameter that tells the server which part to bring, (let's say - how many lines of data) and then override the doGet method of the servlet and deal with the parameter.
I have 2 questions:
1) how do I declare the path of the servlet? where is the connection between the servlet and the request??
2) What do I write in the url of the RequestBuilder (instead of "customerRecord.xml")? do I need to refer to the servlet there or I can keep it like
May be You mean GWT Service?
You need to create 2 interfaces - Service and ServiceAsync and implementation of Service in server package (on same level as client package). Then You define implementation as servlet (in my JBoss 7.1 it just annotation. in older version servlet mapping):
#WebServlet(name="YourService", urlPatterns={"/%module%/YourService"})
public class YourServiceImpl extends RemoteServiceServlet implements YourService
in Your modeule.xml write:
<servlet path="/YourService" class="org.name.YourServiceImpl"/>
and in the end You can call this service from Your code
YourService.App.getInstance().getSomething(new AsyncCallback<Collection<Something>>() {
#Override
public void onFailure(Throwable caught) {
new MessagePopup("Error: " + caught.getMessage()).center();
}
#Override
public void onSuccess(Collection<Something> result) {
}
});
Interfaces You can create from Your beloved IDE. It's much simpler)
One think which still bothering me - I cannot specify path for servlet in another module.
Related
I have a web application deployed to JBOSS. It contains dependency to jersey-rx-client-rxjava package and one of the packages has transient dependency to resteasy-jaxrs.
I have the following code.
RxObservable.newClient()
.target(fullURL)
.request()
.header("Authorization", "Bearer " + config.getApiKey())
.rx()
.post(javax.ws.rs.client.Entity.entity(context, MediaType.APPLICATION_JSON_TYPE), AIResponse.class)
.map(new Func1<AIResponse, String>() {
#Override
public String call(AIResponse res) {
return res.getType();
}
})
.subscribe(new Action1<String>() {
#Override
public void call(final String type) {
Log.info(type);
}
}, new Action1<Throwable>() {
#Override
public void call(final Throwable throwable) {
//async.resume(throwable);
Log.error(throwable.getMessage(), throwable);
}
}, new Action0() {
#Override
public void call() {
//async.resume(throwable);
Log.info("Done");
}
});
At this line, the following exception is thrown.
final JerseyInvocation invocation = (JerseyInvocation) getBuilder().build(name, entity);
Why does the build method return org.jboss.resteasy.client.jaxrs.internal.ClientInvocation, instead of JerseyInvocation?
2017-03-20 12:18:43,678 ERROR [com.optawork.bot.CustomResource] (default task-2) org.jboss.resteasy.client.jaxrs.internal.ClientInvocation cannot be cast to org.glassfish.jersey.client.JerseyInvocation: java.lang.ClassCastException: org.jboss.resteasy.client.jaxrs.internal.ClientInvocation cannot be cast to org.glassfish.jersey.client.JerseyInvocation
at org.glassfish.jersey.client.rx.rxjava.JerseyRxObservableInvoker$2.call(JerseyRxObservableInvoker.java:89)
at org.glassfish.jersey.client.rx.rxjava.JerseyRxObservableInvoker$2.call(JerseyRxObservableInvoker.java:83)
at rx.Observable.unsafeSubscribe(Observable.java:10142)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.subscribe(Observable.java:10238)
at rx.Observable.subscribe(Observable.java:10205)
at rx.Observable.subscribe(Observable.java:10086)
at ai.api.AIDataService.converse(AIDataService.java:601)
Why does the build method return org.jboss.resteasy.client.jaxrs.internal.ClientInvocation, instead of JerseyInvocation
It's just how the JAX-RS Client API is designed. When we try to call ClientBuilder.newBuilder (which is done internally), the JAX-RS API does a service lookup for any implementation of the JAX-RS Client API. If there is none, it falls back to Jersey. The problem is that when the service lookup is done, RESTEasy's client is found on the classpath.
The Jersey RX API has a from(Client) method that we can user, instead of the default newClient. This will allow us to pass an explicit JerseyClient instead of using the JAX-RS API ClientBuilder.newBuilder/newClient
// actual JerseyClient which implements Client
Client client = new JerseyClientBuilder().build();
RxObservable.from(client)
JerseyClientBuilder has pretty much the same API as the JAX-RS ClientBuilder, so you can use it pretty much the same way.
Is it possible to have the AppEngine dev server output a quick log message to the eclipse console every time it serves a static file?
For example, if my website loads "background.gif" (as a static file from the file system), I would like to see a line like "GET request for static file /war/resources/images/background.gif by 127.0.0.1" show up in the Eclipse console.
Maybe there is a command-line switch for tomcat (the server that appengine uses locally)? I couldn't find anything relevant here... But I did find some documentation about an "access log valve (?!?)" which might look promising, but I don't know if this does what I am looking for, or even if it does, how I can get any potential output to show up in the Eclipse console.
You can use a servlet Filter to intercept all requests:
public class LoggingFilter implements Filter {
private static final Logger log = Logger.getLogger(LoggingFilter.class.getName());
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = ((HttpServletRequest) request);
log.info(httpRequest.getMethod() + " request for " + httpRequest.getRequestURI() + " from " + httpRequest.getRemoteAddr());
request.getRequestDispatcher(httpRequest.getRequestURI()).forward(request, response);
}
#Override
public void destroy() {
}
}
The only problem is that you can not distinguish between requests static and dynamic content. In order to do so, you could put all static content under one directory and that map this Filter to only that path.
I use the GWT RequestBuilder, and for testing purposes, I'd like to load a json file in the server.
It works perfectly with the DevMode, but throw a 404 error with GWTTestCase.
With RPC, there is a fix adding <servlet path=".." class="..."/>, but what can I do with static content ?
I could easily use #TextResource, but it's not the goal of my UnitTest (which is in fact a functionnal test)
Static resources can be bundled with a module by putting them in the module's public path.
I used (once again) Thomas's answer to resolve the problem. My module is io.robusta.fora.comments.Comment.gwt.xml and I've put my user.json file in the io.robsuta.fora.comments.resources package.
I had so to add in Comment.gwt.xml file : <public path="resources"/>
Then the GWTTestCase is straightforward :
public class GwtRestClientTest extends GWTTestCase{
#Override
public String getModuleName() {
return "io.robusta.fora.comments.Comments";
}
public void testGET(){
String base = GWT.getModuleBaseURL();
System.out.println(base); //-> http://192.168.0.10:53551/io.robusta.fora.comments.Comments.JUnit/
GwtRestClient client = new GwtRestClient(base); //base url
AsyncCallback<String> cb = new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
System.out.println(result);//->{id:1,email:"jo#robusta.io"}
finishTest();
}
#Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
};
client.GET("user.json", null, cb);//fetch my json file with no params
delayTestFinish(3000);
}
}
I created a app with GWT+requestfacotry(MVP)+GAE. There are some service or method exposed to GWT client ,such as
1.create
2.remove
3.query
I want to add authorization function to "create" and "remove" ,but not to "query".
I did it with servlet filter :
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
UserService userService = UserServiceFactory.getUserService();
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (!userService.isUserLoggedIn()) {
response.setHeader("login", userService.createLoginURL(request.getHeader("pageurl")));
// response.setHeader("login", userService.createLoginURL(request.getRequestURI()));
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
filterChain.doFilter(request, response);
}
My question is how to identify what request (I mean the request will route to which class and service )coming in ? There are some head fields contain the module name ,but I don't it is the security way to do.
Is it possible to get RequestFacotry relevant class from http request ?
Thanks
It's hard to do this within the servlet-filter. Instead you can provide a custom decorator within the RF ServiceLayerDecorator chain. Implementation can looks like this:
import com.google.web.bindery.requestfactory.server.ServiceLayerDecorator;
public class SecurityDecorator extends ServiceLayerDecorator {
#Override
public Object invoke( Method domainMethod, Object... args ) {
if ( !isAllowed( domainMethod) ) {
handleSecurityViolation();
}
return super.invoke( domainMethod, args );
}
}
To register the additional decorator, provide a custom RF servlet:
import com.google.web.bindery.requestfactory.server.RequestFactoryServlet;
public class SecurityAwareRequestFactoryServlet extends RequestFactoryServlet {
public SecurityAwareRequestFactoryServlet() {
super( new DefaultExceptionHandler(), new SecurityDecorator() );
}
}
and register it in your web.xml:
<servlet>
<servlet-name>gwtRequest</servlet-name>
<servlet-class>com.company.SecurityAwareRequestFactoryServlet</servlet-class>
</servlet>
I have example project StockWatcher using requestbuilder to communicate with servlet (this example). I want to make servlet asynchronous. I have added the following lines to the doGet method:
final AsyncContext ac = request.startAsync();
ac.setTimeout(1 * 60 * 1000);
ac.addListener(new AsyncListener() {
#Override
public void onError(AsyncEvent arg0) throws IOException {
System.out.println("onError");
}
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("onComplete");
queue.remove(ac);
}
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("onTimeout");
queue.remove(ac);
}
#Override
public void onStartAsync(AsyncEvent arg0) throws IOException {
System.out.println("onStartAsync");
}
});
queue.add(ac);
added asynchronous annotation: #WebServlet(asyncSupported=true)
and changed the rest of doGet method with:
PrintWriter out = ac.getResponse().getWriter();
out.println("Something");
out.flush();
Now there is nothing returning. What do I wrong? Have to change something in client side? Glassfish 3 does not show any errors.
You are not doing anything wrong. GWT uses servlet 2.5 and it blocks if you try something async. I've the same problem right now although I use Vaadin (which uses GWT). A link I've found on the topic: http://comments.gmane.org/gmane.org.google.gwt/48496
There is a page claiming to have the problem solved: http://blog.orange11.nl/2011/02/25/getting-gwt-to-work-with-servlet-3-async-requests/
I have not been able to try this out yet.