Proper ActiveWeb configuration for simple app: server output is empty - java

I am fighting with ActiveWeb currently. I found, as it seems to me, that it's manual here http://javalite.io/activeweb contains a lot of desinformation.
First it says ActiveWeb is zer-configuration, which is not true. web.xml is still required. Also configuration in java is required. For example, file AppBootstrap.java should be present in appropriate location.
Second, I can't find it yet, how to configure views to work.
I have the following controller
package app.controllers;
import java.util.Date;
import org.javalite.activeweb.AppController;
public class GreetingController extends AppController {
public void index() {
}
public void hello() {
view("date", new Date().toString());
view("name", param("name"));
}
}
and it works as I see in debugger. When I open http://localhost:8080/testapp/greeting/hello, the breakpoint in hello() method is reached.
Unfortunately, the file hello.ftl, located in WEB-INF/views/greeting/hello.ftl is apparently ignored, because the browser output is empty.
Simultaneously, it is 100% empty, i.e. there are no HTTP headers at all. This points to suggestion, that some general config is missing.
Also, I have empty output on EVER query, including
http://localhost:8080/testapp
http://localhost:8080/testapp/greeting
http://localhost:8080/testapp/abracadabra
while some of the requests should return errors or service messages.
Request
http://localhost:8080/
returns 404 which means container is working normally.
My web.xml is follows:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>dispatcher</filter-name>
<filter-class>org.javalite.activeweb.RequestDispatcher</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>css,images,js</param-value>
</init-param>
<init-param>
<param-name>root_controller</param-name>
<param-value>home</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>dispatcher</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
UPDATE
When I removed root_controller parameter from web.xml, the server started to answer with directory listing on
http://localhost:8080/testapp
Other answers are still completely empty
UPDATE 2
Apparently WEB-INF/views/layouts/default_layout.ftl should be present. Otherwise the results will be empty and no error will be reported.

something is definitely mis-configured in your app. Can you post sources somewhere on Github?
You can also clone this app: https://github.com/javalite/activeweb-bootstrap

Related

About Welcome Page and Accessing Web Service Methods

I have a problem with configuration ( or basic understanding how things work at background). I create a JAVAEE project by checking Web application and ReSt api checkbox ( in intellij with glassfish 5.0). I have sample code below which web methods work but welcome page does not work. My web.xml and sample web service methods are below.
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>test</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
**<url-pattern>/ *</url-pattern>**
</servlet-mapping>
#Path("/RestTest")
public class TestString {
#Context
ServletContext context;
#GET
#Path("insertdb/{param1}/{param2}")
#Produces(MediaType.APPLICATION_JSON)
public Object writeToDb( #PathParam("param1") String param1
,#PathParam("param2") String param2){
try{
String password= context.getInitParameter("DbPassword");
Class.forName("org.mariadb.jdbc.Driver");
Connection dbCon = DriverManager.getConnection(
"jdbc:mariadb://xxx/testdb", "root", password);
PreparedStatement stmt=dbCon.prepareStatement(
"INSERT INTO TestTable VALUES(?,?)");
stmt.setString(1,param1);
stmt.setString(2,param2);
stmt.executeUpdate();
dbCon.close();
return "Success";
}catch(SQLException | ClassNotFoundException ex){
return ex.toString();
}
}
#GET
#Path("sum/{sum1}/{sum2}")
#Produces(MediaType.TEXT_HTML)
public String calculateSum(#PathParam("sum1") int param1
,#PathParam("sum2") int param2){
return ""+(param1 + param2);
}
If i change this line url-pattern "/*" to "/"
then welcome page is accessible but not methods.
Thus what i want is, having a welcome page which i will use for documentation for my web services(i dont want SOAP) and web methods must work by adding / to base url. How can i achieve that and what is difference between /* and /
See here for explanation of differences:
What is url-pattern in web.xml and how to configure servlet
Generally for a rest api it is best to use a path specific to all rest calls, for instance http://localhost/mywebapp/rest/...
Something like:
<servlet-mapping>
<servlet-name>jersey-servlet/servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
You only want jersey serving particular URLs when it is bundled in a WAR that also includes html pages.
To answer your question, difference between "/" and "/*"
A mapping that contains the pattern "/" matches a request if no other pattern matches. This is the default mapping. The servlet mapped to this pattern is called the default servlet. The default mapping is often directed to the first page of an application. Example :
Both requests will display same contents from index.jsp
http://myhost.com/index.jsp
and
http://myhost.com/
Now, a mapping that contains "/*" overrides all other servlets, including all servlets provided by the servlet container such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets.
Possible solution for your issue
Change the URL pattern to specific instead of default pattern.
<servlet>
<servlet-name>webservice</servlet-name> //servlet name
<servlet-class>com.rest.MyRestServlet</servlet-class> //servlet class
</servlet>
<servlet-mapping>
<servlet-name>webservice</servlet-name> //servlet name
<url-pattern>/RestTest/*</url-pattern> //all webservice request
</servlet-mapping>
All the web service request are accessible through
http://myhost.com/RestTest/
You may also be interested to look
What is URL-pattern in web.xml and how to configure servlet
Basics of Java Servlet
Servlet configuration and url-pattern
As you highlighted, your problem revolves around those four lines:
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
As Jim Weaver mentioned, it's a matter of url-pattern.
Solution(s)
You may consider three solutions (from the most-preferred to least-preferred):
dedicated REST URL: the easiest way is to have a dedicated url-pattern such as /rest/* for your web services. You can benefit some assets such as url hierarchy or you can easily implement a security framework over it.
URL rewriting may be an option and this answer suggests some library. I haven't tested those libraries myself
Page redirection can be an option to go around REST filtering but in the specific case of having the url-pattern at /*, I have to say I'm not sure if it's working for the reason I'll explain in next section
now a bit of explanation of what happened
Why setting the url-pattern at /* prevent from accessing the welcome page?
Actually, it's not only the welcome page that is not accessible: it's all the resources under the defined url-pattern. Whatever get in touch with REST stays with REST... Here is the schema taken from JSR 339 Appendix C:
With a GlassFish 5.0, I guess you're using JAX-RS 2.1 (JSR 370) but the sections I'm quoting have the same content
Without entering into detail, it is visible that only ContainerRequest Filters are executed in the process. Especially, it's worthy to notice that after Request Matching, requests are not forwarded to any servlet in a sense that standard resources are not reachable, unless specified by the REST method.
It's also worthy to highlight the fact the servlet filters are executed beforehand (leveraging this point is absolutely vital for managing security for example). I did not find back the source proving this point but I know it's somewhere on the web ^^.
Request matching is defined at section 3.7.2. In a nutshell, it is in three steps where the first one is the most important for your question, especially at step D:
Identify a set of candidate root resource classes matching the request
c. ...
d. If [the set of classes whose path matches the request URL] is empty then no matching resource can be found, the algorithm terminates and an implementation MUST generate a NotFoundException (404 status) and no entity
e. ...
highlights are mine.
The two last steps are
Obtain a set of candidate resource methods for the request
Identify the method that will handle the request
TL;DR
What happened when you set <url-pattern>/*<url-pattern> and tries to access to your welcome page (or any page actually):
Your server receives the GET request
If there are filters (such those from a security framework), there are executed
REST enters the scene
Pre Match filters are executed (none if your case)
Fetch your root resources classes (in your example, all classes in the test package)
Find if one of those class match the request URL
None are found, a 404 status is returned
To avoid unnecessary URL conflicts, the best options would be having a dedicated URL for your REST methods
If you mention in web xml like following all the request receive by 'Jersey Web Application' servlet. so request to index.jsp also redirect to 'Jersey Web Application' servlet
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
To avoid this add some prefix to the url to separate rest request like following
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>rs/*</url-pattern>
</servlet-mapping>

Java + TomEE. Websockets and Servlets in one project?

I'm writing a simple game with JavaEE Websocket technology. Using JSR356, my server-side socket class looks like following:
#ServerEndpoint(
value = "/sock",
decoders = { SocketDecoder.class }
)
public class CardsSocket {
....
#OnMessage
public void onMessage(final SocketInput message, final Session session) {
...
}
...
}
It works perfectly fine, and has no issues. But then I decided to create also some web page for info and stuff. So, without changing anything on previous class, I have created a new one:
#ServerEndpoint(value = "/cards")
public class CardsWebPage extends HttpServlet {
#Override
public void doGet(...) {
...
}
}
And configured web.xml file in WEB-INF directory.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<servlet>
<servlet-name>CardsWebPage</servlet-name>
<servlet-class>server.CardsWebPage</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CardsWebPage</servlet-name>
<url-pattern>/cards</url-pattern>
</servlet-mapping>
</web-app>
And there began troubles. My servelet works - browser shows page on localhost:8080/cards, but client-side socket class can no longer initiate - it falls with Exception:
"javax.websocket.DeploymentException: The HTTP response from the server [HTTP/1.1 404 Not Found] did not permit the HTTP upgrade to WebSocket"
, and nothing seems to fix it. Have I missed some documentation? Is it impossible for a single project to contain both servlets and websocket classes? Because, if I delete web.xml file, then sockets are starting to work like before. Server startup logs containing no warnings or errors in both cases.
Yeah, perhaps sparks is right, and I should simply deploy multiple projects.
Hi why decorating CardsWebPage with #ServerEndpoint? Nothing or if you can to get rid of web.xml #WebServlet should be fine.

Message level Jax-WS service

I'm trying to create a WebService stub. I like to react to all of the request in one single place. I have a sample value generator, which handles the type of the request and creates a sample response, so I don't need the code-generation things with a lots of classes. Only a really simple one.
I have found http://jax-ws.java.net/nonav/2.2.1/docs/provider.html WebServiceProvider which is exactly for getting raw SOAP messages, and create a response in a single place.
The main problem is I'm new to this magical EE world :) and I simply can not start WebServiceProvider sample anyway.
I have Spring, SpringSource ToolSuit, Axis installed/configured, all of the other things are working.
Thank you all for your help, and please excuse me if the question is too simple for you. Maybe I just did not find/read something.
M.
Finally I have found the solution (thanks for the help from my workmates).
If you are using JAX-WS, there is a simple solution.
You need a sun-jaxws.xml in your WEB-INF folder containing the following:
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
<endpoint
name="RawWS"
implementation="com.stg.pack.MyServiceProvider"
url-pattern="/HotelServices200631"/>
</endpoints>
And you need a com.stg.pack.MyServiceProvider class which looks like:
package com.stg.pack;
#ServiceMode(value = Service.Mode.MESSAGE)
#WebServiceProvider(portName = "ThePortNameOfWebService",
serviceName = "TheNameOfWebService",
targetNamespace = "http://www.example.com/target/namespace/uri")
public class MyServiceProvider implements Provider<SOAPMessage> {
#Override
public SOAPMessage invoke(SOAPMessage request) {
SOAPMessage result = null;
// create response SOAPMessage
return result;
}
}
And before I forget, you need to define some things in web.xml:
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>RawWS</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RawWS</servlet-name>
<url-pattern>/TheNameOfWebService</url-pattern>
</servlet-mapping>
If you use it like this, all of the request are handled by the invoke method.
you basically must deploy your provider to some sort of Container. developing in J/EE basically mandates that you compile some sort of EAR or WAR or JAR and tell an app server to deploy it (be that app server a JBOSS, glassfish, Weblogic, Websphere, Tomcat, etc).
Have you tried doing this?
it also may be possible to test your provider using the javax.xml.ws.Endpoint class, although I have to admit I've never chosen to per-sue this in favor of deploying to an app server.

doFilter not getting called

Could you help to check why doFilter not getting called
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<filter>
<filter-name>roseFilter</filter-name>
<filter-class>net.paoding.rose.RoseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>roseFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
</web-app>
class signature:
import org.springframework.web.filter.GenericFilterBean;
public class RoseFilter extends GenericFilterBean {
404 is returned while call http://localhost:8080/hello/world, I set the breakpoints at
doFilter, it seems doFilter not called?(I tried tomcat 6.0.18, 6.0.29, jdk1.6)
The filter won't be invoked when:
The filter class is missing in the classpath and/or is not loadable or instantiable. You should however have noticed it in the server's startup logs. Solution is to be found based on the interpretation of the exceptions/errors found in the server logs.
There's another filter running before in the chain which isn't calling FilterChain#doFilter(), but rather RequestDispatcher#forward() or include() which caused the subsequent filters in the chain being completely skipped (when they do not listen on FORWARD or INCLUDE dispatchers; they by default only listens on REQUEST dispatcher). Solution is either to fix the wrong filter, or to add <dispatcher>FORWARD</dispatcher> etc accordingly, or to rearrange the filter declarations in web.xml so that your new filter comes before the another filter (you in turn only need to ensure that your new filter is using the FilterChain#doFilter() properly :) ).
The request URL is plain wrong. You used http://localhost:8080/hello/world. With a filter listening on /*, this means that the webapp context should be ROOT or at least /hello. Verify your webapp context. I'd just retry with an URL which points to a valid JSP/Servlet inside the same webapp which generates a non-404 response. Does the filter then get called as well?
What's the web request look like? Can you try changing your url-pattern to *.jsp instead of / * ? If you are using something other than pure JSP then change it to whatever the request ending extension is (like for struts it is usually *.do).

Calling a default servlet first in Java web application [duplicate]

This question already has answers here:
Change default homepage in root path to servlet with doGet
(2 answers)
Closed 7 years ago.
I want my SampleServlet to be called first whenever my java web application is accessed in this manner :
http://server:8080/appname/
Is there any way to implement this?
Use a Servlet filter to call your Servlet.
If you want to make a servlet your homepage then this worked for me on http://feelitlive.com/
<welcome-file-list>
<welcome-file>homepage</welcome-file>
</welcome-file-list>
...
<servlet>
<description>Shows stuff on the homepage</description>
<display-name>Homepage Servlet</display-name>
<servlet-name>HomepageServlet</servlet-name>
<servlet-class>com.cantorva.gigcalendar.servlets.HomepageServlet</servlet-class>
</servlet>
...
<servlet-mapping>
<servlet-name>HomepageServlet</servlet-name>
<url-pattern>/homepage</url-pattern>
</servlet-mapping>
That means that that users arriving at your application via the URL you specified will be welcomed by your servlet. It also creates an alias for the homepage at "/homepage" but you don't have to use that.
If you want to run some code on start-up then asalamon74's answer looks right.
Not sure what you mean but you need to map your servlet to "/"
<servlet-mapping>
<servlet-name>SampleServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Not sure what is your aim, but web application initialization can be achieved by ServletContextListener:
public class AppListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// place your code here
}
public void contextDestroyed(ServletContextEvent event) {
}
}
and later in web.xml:
<web-app>
<listener>
<listener-class>
package.AppListener
</listener-class>
</listener>
...
</web-app>
If you want to run code on start-up indeed asalamon74's answer should be fine. If you have a legacy situation and you must use a servlet, the parameter load-on-startup can do the trick for you:
<servlet>
<servlet-name>SampleServlet</servlet-name>
<display-name>SampleServlet</display-name>
<description>Sample Servlet</description>
<servlet-class>...</servlet-class>
<init-param>...</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
The load-on-startup tag specifies that the servlet should be loaded automatically when the web application is started; the number value just gives a loading order to those loading on startup. If no value is specified, the servlet will be loaded when the container decides it needs to be loaded - typically on it's first access.

Categories