Eclipse: Thrift inside Tomcat Servlet, ClassNotFoundException TException - java

I'm trying to make a Java servlet that can make Apache Thrift calls, but I'm having trouble starting the servlet.
I have a thrift client, a Java class for making calls to the thrift server
public class ThriftClient {
static TTransport transport;
static TProtocol protocol;
static MyService.Client client;
static long xtk_pointer;
public static void openSocket() throws TException {
transport = new TSocket("localhost", 9090);
transport.open();
protocol = new TBinaryProtocol(transport);
client = new MyService.Client(protocol);
}
and I have a java servlet which opens a socket through the thrift client
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
out.println("Hello World");
}
void startThrift(String [] args) {
try {
ThriftClient.openSocket();
However, when I try to run this servlet (using eclipse and a tomcat server), I get an error like
SEVERE: A child container failed during start
and a ClassNotFoundException for org.apache.thrift.TException
EDIT: All I had to do was include the thrift jars into the Tomcat Server's classpath. See my answer below
I have used the thrift client already without any ClassNotFoundExceptions, and the servlet works on its own as well. However, once I add ThriftClient.openSocket(); into the servlet, it breaks, so I have a feeling Thrift and Tomcat are clashing somehow. Any ideas?
Edit: The weird part is that I never call the method startThrift() but I still get the error.

While you included the thrift jars into your project, you also have to add them to the Tomcat library as well
First make sure your external jars are in your project Java Build Path...
right click your project, click Properties
Under Deployment Assembly, click Add...
Double click Java Build Path Entries... and select the jars/libraries you want to include

Related

Writing tests for grizzly sever with jersey with jar dependency

I start the server from the terminal via the java -jar target/test-service-1.0-jar-with-dependencies.jar command
However when running tests from Intellij Idea, I just cannot figure out how to start the server..
This is the current code, which doesn't work
private HttpServer server;
private WebTarget target;
#Before
public void setUp() throws Exception {
// start the server
server = Main.startServer();
// create the client
Client c = ClientBuilder.newBuilder().register(JacksonFeature.class).build();
// uncomment the following line if you want to enable
// support for JSON in the client (you also have to uncomment
// dependency on jersey-media-json module in pom.xml and Main.startServer())
// --
// c.configuration().enable(new org.glassfish.jersey.media.json.JsonJaxbFeature());
target = c.target(Main.BASE_URI);
}
This is my startServer code
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
ResourceConfig rc = new ResourceConfig().packages("com.test.service").register(JacksonFeature.class);
EncodingFilter.enableFor(rc, GZipEncoder.class);
rc.register(LoggingFilter.class);
rc.register(MultiPartFeature.class);
rc.register(CORSResponseFilter.class);
// rc.property("config", configParams);
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
//httpServer.getServerConfiguration().addHttpHandler(shh);
return httpServer;
}
It should just start by itself. But for testing you probably want to control when it starts. You can pass false as the third argument to the server factory method. That way you control when it should start.
You can call start and stop on the HttpServer instance in your before and after methods in your test. You'll need to update the code in the Main class also, to call start().
You might also want to check out Jersey Test Framework. Here you won't need to start and stop any servers. The framework will handle it for you. It also makes your tests more configurable than your current set up. Say you only want one resource registered or you want to inject some mocks services. Personally, I would go with the test framework.

List servlets in a java webapp (running in tomcat)

I am trying to re-package a relatively big java webapp which I did not code and for which the project configuration was lost.
I setup a first packaging, and deployed it in tomcat. Now to understand it, I'd like to get a list of the servlets that started successfully or failed, with corresponding access url.
Is there a way to get that list (from some startup log maybe)?
Some details: the webapp uses gwt (which I don't master), I use tomcat7 on ubuntu. I am not against a solution using another servlet container, if practical.
I would write a simple JSP or ServletContextListener to read all the ServletRegistratioins from the servlet context and display them.
So your JSP/ServletContextListener would read the data from
servletContext.getServletRegistrations();
and just display it.
Edit
#WebServlet(urlPatterns = "/mappings")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = -7256602549310759826L;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
Map<String, ? extends ServletRegistration> registrations = req
.getServletContext().getServletRegistrations();
for (String key : registrations.keySet()) {
ServletRegistration registration = registrations.get(key);
writer.write("Name: " + registration.getName());
writer.write("<br>Mappings:");
for (String mapping : registration.getMappings()) {
writer.write(mapping);
}
}
// of course you can write that to log or console also depending on your
// requirement.
}
}
You can see started modules and paths in Tomcat by double click at Tomcat and see Modules tab.

Camel with Jetty

I am playing around with Camel for the first time. My trial project is to write an application that receives an HTTP GET request (using Jetty) and passes on the request via Thrift to another server. The answer received is then passed back to the client. (i.e. I'm writing a data switch or a middleware application if you will between an http-get request and a Thrift-enanbled server.)
I have the non-camel version perfectly and I am now trying to put the camel-equivalent together. For now I am only trying to get the jetty request written to a file.
This is what I have so far:
public class CamelMedicalService {
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();
context.addRoutes(new MedicalServiceRouteBuilder());
context.start();
// Wait a minute and then stop all.
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
context.stop();
}
}
and the RouteBuilder:
public class MedicalServiceRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("jetty:http://localhost:8080").to("file://test");
}
}
I am currently getting
java.lang.ClassNotFoundException: org.eclipse.jetty.util.component.Destroyable... I am not sure how to resolve this. How should I set this up so that I can receive an http request and pass it to the file?
Like in the comments, please check if jetty-util.jar is in the classpath, if not, you can copy it to your WEB-INF/lib directory.

Java - Create a web service from an available class

I had a java project and after lots of research I managed to convert it to a Dynamic Web Project in Eclipse. Now I want to add a new Web Service to it. I have already developed a class. I want to convert it to a standard Web service so I can call it from my silverlight application. Here's my current class:
public class MyWebService
{
#Resource
WebServiceContext context;
#WebMethod
public String ProcessQuery(#WebParam(name="query") String q)
{
MessageContext messageContext = context.getMessageContext();
HttpServletRequest request = (HttpServletRequest) messageContext.get(SOAPMessageContext.SERVLET_REQUEST);
// now you can get anything you want from the request
}
public static void main(String[] args) throws Exception
{
String address = "http://127.0.0.1:8023/_WebServiceDemo";
Endpoint.publish(address, new MyWebService());
new DocumentServer();
System.out.println("Listening: " + address);
}
}
How can I do it in Eclipse? Please post a link to a tutorial or a quick step by step guide. I'm a .Net developer and I'm very new to Java.
Thank you.
PS: So basically I want to publish this service in a standard way rather than calling this main function and using Endpoint.publish() method.
The Eclipse wiki has a tutorial using the Web Tools Platform to do just what you are looking for. It requires WTP and Tomcat, if you don't have those already available to Eclipse. It starts with an unannotated class and finishes with a WSDL and test client. It allows you to view generated SOAP messages.
To create, it instructs you to select the file you want to convert into a web service and run File -> New -> Other... -> Web Services -> Web Service. Then you click Next, move the slider to the Start Service position, and client to Test Client. You select Monitor the Web Service and then click Finish. Then you can play with your Test Client and see your generated WSDL.
Note that the above paragraph is a summary of the tutorial, which you can find in full at the provided link.

Wrap the default servlet but override the default webapp path

I have a folder of static html,imgs,flash content that lives outside of the webapp folder. Right now I'm using a symbolic link to map that folder into my webapp directory. The problem i have is when I undeploy my application it follows the symbolic link and deletes all these files.
One of the solutions I'm trying to implement is a special servlet that wraps the default servlet but uses a different relative path. I'm having trouble finding out how to wrap the default servlet in a way that overrides the default servlet path.
Here is what I'm working with:
public void doGet(final HttpServletRequest req, final HttpServletResponse resp)
throws ServletException, IOException {
final RequestDispatcher rd = getServletContext().getNamedDispatcher("default");
final HttpServletRequest wrapped = new HttpServletRequestWrapper(req) {
#Override
public String getServletPath() {
return "/usr/depot/repository";
}
};
rd.forward(wrapped, resp);
}
You can override DefaultServlet with your own implementation. You can perfectly subclass it, it's a public class. Here are the functional specifications of the DefaultServlet, you need to adhere it.
On the other hand you can ignore DefaultServlet and go for your own solution, an example can be found here.
You can either write your own servlet to serve static content (which is not that hard) or try to extend rather than wrap the DefaultServlet. Either way, your resulting servlet will have be configured in place of default in your web.xml (using "default" as servlet-name).
That said, DefaultServlet will only serve static content from under your webapp context; in order to change that you'll have to create / bind to JNDI your own ProxyDirContext instance pointing to the outside folder and I'm not sure whether that will work; its configuration process is rather involved.
Trying to override servlet path will not get you anywhere.
We have a similar problem that we need to share some files generated by CMS among several applications. Symlink is the easiest way to do this if you are not using Windows.
We setup 2 accounts for CMS and Tomcat. The files are read-only to Tomcat so it can't delete them.
You can also write a small Tomcat extension so it can look for files in multiple places. See this web site,
http://blog.bazoud.com/post/2009/05/12/Multiples-docbases-avec-tomcat
Your current approach won't work. Tomcat needs to load up all the resources in a cache on deploy for it to be available. It's too late to change that in request processing. This extension allows Tomcat load resources from multiple directories. The drawback of this approach is that you have to put a small JAR in server/lib.
That's not a good idea.
Web containers or application servers can be deployed behind Web servers or you can simply use a Web server in conjunction with your container. Just put your static files under that and refer to them by absolute path.
There's really no need for this kind of hack (sorry but that's what it is).
Either that or simply deploy them with the Web app.
You can change to a different path within your webapp context. Here's an example which does differential serving depending on whether the client's User-Agent supports ES6:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
RequestDispatcher rd = getServletContext().getNamedDispatcher("default");
HttpServletRequest wrapped = new HttpServletRequestWrapper(req) {
#Override
public String getServletPath() {
String prefix = supportsES6(req) ? "/es6" : "/es5";
String newPath = prefix + req.getServletPath();
if (newPath.endsWith("/")) newPath += "index.html";
return newPath;
}
};
rd.forward(wrapped, resp);
}
However, "es5" and "es6", even though we use the initial slash, are subdirectories of the webapp's ordinary context. It's not possible to break outside of the context directory using this method.
I have open-sourced a custom servlet that serves files from an arbitrary base path. Additionally, it supports file browsing inside nested compressed archives.
It's available here: https://bitbucket.org/teslamotors/zip-listing/overview

Categories