I've finished working on some lengthy method launched from the client side using GWT-RPC. doSomething()
Suppose the following classes: (copied from GWT: invoke the same RPC-methods on the server-side as on the client-side)
//MyClassService.java - client package
#RemoteServiceRelativePath("myService")
public interface MyClassService extends RemoteService{
public doSomething();
}
//MyClassServiceAsync.java - client package
public interface MyClassServiceAsync{
public void doSomething(AsyncCallback<Void> callback);
}
//MyClassServiceImpl.java - server package
public class MyClassServiceImpl extends RemoteServiceServlet implements MyClassService{
#Override
public void doSomething()
{
//interacts with DB and another stuff
}
}
Now I'd wish to launch the very same method from my ScheduledTask infrastructure but I don't know if this is posible. The ScheduledTask infrastructure is in the server side. I've barely worked the networking side of any language and I'm lost. So far I've tried:
MyClassServiceImpl a = new MyClassServiceImpl();
a.doSomething();
The problem appear (NullPointerException) as soon as it hits the first doSomething() line with some call to getServletConfig().getServletContext() as it returns null.
Plus, MyClassServiceImpl init() method which I've overrided so it reads some params from web.xml, is also not invoked.
Thx in advance!
Not specifically GWT related, but:
1) Move your initialization parameters out of web.xml. It is an awful mechanism and should never have been in the servlet specification. If you build a war file, it means that you have to rebuild the war file every time the parameters changes. And if you need to different parameters for dev, acceptance, and prod, that means three separate war files. Instead put a properties file somewhere on the file system. Start your web container with an extra Java parameter setting a value for a custom property, for example -Dmyapp.conf=d:\\conf\\apps\\myapp.conf.
2) Now that you have moved your parameters out of web.xml, you can write a standalone class that initializes itself from the system defined parameters file (System.getProperty("myapp.conf")), with no dependency on anything servlet related.
3) Use the class from your GWT servlet, your scheduler, etc...
Related
I've been going through this tutorial and they added a web service class instance to a hashSet, like this:
public class MessageApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public MessageApplication() {
singletons.add(new MessageRestService());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
I do not understand what the purpose of it is... I thought you could just access the web service with a URL
You made a class, this class is able to handle web requests. But this class has to be hosted somewhere. This means, this class has to be activated by a URL route. In this case you're using JBOSS.
In the first option of the tutorial, MKyong shows you how to configure RESTEasy Bootstrap (a bootstrap to load references) to map the URL with your class. This is done in web.xml and configures some kind of scanner that will map a certain URL with your class.
The second option is not using RESTEasy Bootstrap and you have to add your class to a collection of long living objects in your application manually. This is done defining the Application (MessageAplication) and defining it in the web.xml.
Yes, you can access the webservice via a URL, but the server needs to know what to do with calls to a certain URL.
Yours is one way (the bootstrap version) of telling the application server where to look for JAX-RS resources: http://www.mastertheboss.com/resteasy/resteasy-tutorial (Step #4)
There is a (newer) alternative, depending on which server and RESTeasy-version you use, which relies on autoscanning for certain annotations. For RESTeasy on JBoss, it's described at the bottom of the tutorial-page I linked.
We are currently using a sync. web call to send emails. This was done as a quick fix to prove out some basic functionality, but now we need to send the e-mails async. I have the everything pretty much reworked to queue up jobs and then send the emails, but I've run in to one issue. We use FTL for our email templates and before we were passing the servlet context to FTL to get the template folder. Since we are now doing this in a queued job that get's processed by a Spring #Scheduled job, we no longer have access to the web servlet. I've been researching and playing around for awhile now, but I haven't seem to come up with a way that will actually work.
I have a feeling there is some super simple way to get
The code that did the work before looked similar to this:
#PUT
#Produces(MediaType.APPLICATION_JSON)
#Path("someStuffHere")
#Transactional
public function someWebServiceCall(#Context javax.servlet.http.HttpServletRequest req)
{
SomeStuff foo = gotSomeStuff();
sendEmail(req.getServlet(), foo);
}
public sendEmail(Servlet context, SomeStuff foo) //<-- lives in another class somewhere, just showing how FTL uses the servlet
{
Configuration cfg = new Configuration();
cfg.setServletContextForTemplateLoading(context,"communicationTemplates/email");
}
The new code now looks something like this:
public class someClass
{
#Autowired
private SomeRepo someRepo;
#Scheduled(cron = "* */2 * * * ?")
public void sendAnyOutstandingStuffEmails()
{
SomeStuff foo = someRepo.getStuff();
sendEmail(/*how to get context, or a resource so FTL can get the template folder*/, foo)
}
Even though this post is quite old and the author has given another solution a try, it is not necessary to have a servlet context instance in order to load templates. The freemarker documentation states:
Built-in template loaders
You can set up three template loading methods in the Configuration
using the following convenience methods. (Each method will create a
template loader object internally and set up the Configuration
instance to use that.)
void setDirectoryForTemplateLoading(File dir);
or
void setClassForTemplateLoading(Class cl, String prefix);
or
void setServletContextForTemplateLoading(Object servletContext, String path);
http://freemarker.org/docs/pgui_config_templateloading.html
So in this case it should have been possible to configure freemarker to use the ClassLoader (option 2) by naming a class that is on the same level as the templates or to use this class as root node for navigating to the template using relative paths.
I need to create a rest server and client.
I stumbled upon this tutorial which uses sockets. I want to be able to use REST calls, possibly HTTP, because the clients will be actually in different languages.
Instead of using Socket api from java.net.* what should i use ? if i use Socket API can I use c++ and php to communicate with this server? or should i go with REST?
any directions appreciated.
There's a lot of things you can use to create rest services, and then they can be consumed by almost anything. Of particular awesomeness is the ability to hit them in your web browser, just because we're all so familiar with them.
When I need a 'quick and dirty' rest solution, I use Restlet - I won't claim it's the only solution, but it's the easiest I've ever worked with. I've literally said in a meeting "I could have XYZ up in 10 minutes." Someone else in the meeting called me on it, and sure enough, using Restlet I was able to get a functioning REST server running with the (very simple) features I said I would get in the meeting. It was pretty slick.
Here's a barebones server that has one method, returning the current time. Running the server and hitting 127.0.0.1:12345/sample/time will return the current time.
import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.data.Protocol;
import org.restlet.routing.Router;
/**
* This Application creates an HTTP server with a singple service
* that tells you the current time.
* #author corsiKa
*/
public class ServerMain extends Application {
/**
* The main method. If you don't know what a main method does, you
* probably are not advanced enough for the rest of this tutorial.
* #param args Command line args, completely ignored.
* #throws Exception when something goes wrong. Yes I'm being lazy here.
*/
public static void main(String...args) throws Exception {
// create the interface to the outside world
final Component component = new Component();
// tell the interface to listen to http:12345
component.getServers().add(Protocol.HTTP, 12345);
// create the application, giving it the component's context
// technically, its child context, which is a protected version of its context
ServerMain server = new ServerMain(component.getContext().createChildContext());
// attach the application to the interface
component.getDefaultHost().attach(server);
// go to town
component.start();
}
// just your everyday chaining constructor
public ServerMain(Context context) {
super(context);
}
/** add hooks to your services - this will get called by the component when
* it attaches the application to the component (I think... or somewhere in there
* it magically gets called... or something...)
*/
public Restlet createRoot() {
// create a router to route the incoming queries
Router router = new Router(getContext().createChildContext());
// attach your resource here
router.attach("/sample/time", CurrentTimeResource.class);
// return the router.
return router;
}
}
And here's the 'current time resource' that it uses:
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
/**
* A resource that responds to a get request and returns a StringRepresentaiton
* of the current time in milliseconds from Epoch
* #author corsiKa
*/
public class CurrentTimeResource extends ServerResource {
#Get // add the get annotation so it knows this is for gets
// method is pretty self explanatory
public Representation getTime() {
long now = System.currentTimeMillis();
String nowstr = String.valueOf(now);
Representation result = new StringRepresentation(nowstr);
return result;
}
}
JAX-RS is the API for REST in Java. There are a lot of implementations, but the main ones are Jersey (the reference implementation), Apache's CXF and Restlet.
Usually, you don't create a server. You create a web application and deploy it on the server or servlet container. Some servlet containers are embedable into your web application, e.g. Jetty. Poppular free servlet containers are Tomcat, Glassfish, Jetty, etc.
For Restlet, it is not a servlet container. It is a framework that allow you to create a wep application with RESTful styles. So this should not be confused.
If you decide to use servlet container, then the problem is how you can create a web application with the RESTful styles. REST is not a technology - it is a design principle. It is a concept of how you should create the interface.
The design of REST is stateless so you do not need to store the state of the transaction. All information from a request should be sufficient to produce a respose to client.
There are several servlet framework that allows you to implment the REST styles easily. Some of them are very sophisticated, e.g. Spring framework.
Download JBoss 7. Problem solved.
Heres a restful service:
#Path("/myservice")
public class MyService {
#GET
#Produces(MediaTypes.TEXT_PLAIN)
public String echoMessage(#QueryParam("msg") String msg) {
return "Hello " + msg;
}
}
Create a WAR. Deploy. Open up browser and go http://myserver/myapp/myservice?msg=World. Done!
I would say go with an HTTP based RESTful service. It's rapidly becoming a defacto standard. Check my answer to this similar question for pros and cons.
This is the best one out there. Spring MVC which has lot of REST capabilities in itself. This takes just a single jar file to be included. And you are all set to use all it's capabilities. Even as simple as the below guy explained in JBOSS and much more flexibility as well.
http://java.dzone.com/articles/spring-30-rest-example
I use JBoss 6 with RestEasy. I have created a tutorial located here. I hope this helps you.
You're also welcome to see my very simple example for REST server implementation here.
I am trying to create a dynamic proxy that would wrap an EJB around a web service because the application server does not support creating an EJB based web service without a proprietary router project generation.
My thought was to create a dynamic proxy, and some how just start it using an InitServlet. Right now I am kind of stuck on figuring out how to set the annotations dynamically so that I won't get the following error.
class $Proxy0 has neither #WebSerivce nor #WebServiceProvider annotation
at com.sun.xml.internal.ws.server.EndpointFactory.verifyImplementorClass(EndpointFactory.java:277)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.getPrimaryWsdl(EndpointImpl.java:273)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.createEndpoint(EndpointImpl.java:213)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(EndpointImpl.java:143)
Recently I have had the same problem. It seems that most people say is not possible. See http://softwarecarnival.blogspot.be/2009/02/java-annotations-and-proxies.html
If the interface that you have is:
interface XXXInterface{
Result doStuff1(String param1)
}
then a workaround is to create a delegator to the proxy that will also implement the web service.
#WebService
public class WebServiceDelegateToXXXServer implements XXXInterface{
public WebServiceDelegateToXXXServer(XXXInterface actualImplementor){
this.actualImplementor = actualImplementor;
}
public Result doStuff1(String param1){
return actualImplementor.doStuff1(param1);
}
}
Then you will publish
XXXInterface proxy = createProxyAsXXXInterface();
Endpoint.publish(url, new WebServiceDelegateToXXXServer(proxy));
Can I write a module/filter that gets put into the processing pipleline in Tomcat BEFORE the web application even gets run?
Something that I could turn on/off for each web application that tomcat is handling.
is this possible?
So basically it would be a re-usable filter that hooks into the web pipeline that could alter the requests behavior or perform/modify the requests. One example would be to log all ip's, or redirect based on the url, block the request, etc.
If you are using Servlet 3.0 you can. What you do is implement either a ServletContextListener or a ServletContainerInitializer. The code below shows withServletContextListener
#WebListener("auto config listeners")
public class MyListenerConfigurator implements ServletContextListener {
public void contextInitialized(ServletContextEvent scEvt) {
ServletContext ctx = scEvt.getServletContext();
FilterRegistration.Dynamic reg = ctx.addFilter("myFilter", "my.listener.class.MyListener");
...
}
See EE6 docs here. Perhaps the only drawback is that you can add but you cannot remove. And you can only at when the application starts up.
Note: code not tested
Have you considered a ServletContextListener in web.xml?