I have been trying to get parameters from my web.xml file from within my Jakarta JAX-RS resource. My web.xml is as follows:
<web-app>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>terrible.package.name</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/api/v1/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>max-customers-size</param-name>
<param-value>10</param-value>
</context-param>
</web-app>
In my test setup, I am running my web app with Jetty:
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
WebAppContext ctx = new WebAppContext("target/the-finished-servlet.war", "/");
server.setHandler(ctx);
server.start();
}
And I have the following user resource defined using jakarta:
#Path("user")
public class UserResource {
ServletContext context;
#Context
public void setServletContext(ServletContext context) {
this.context = context;
System.out.println("setting to: " + context);
}
#GET
#Path("/list")
#Produces(MediaType.APPLICATION_JSON)
public Response getListOfAllUsers(final #Context HttpHeaders hdrs) throws SQLException {
System.out.println(context.getInitParameter("max-customers-size"));
return Response.ok("{}").build();
}
}
The context is always null, which makes absolutely no sense. The setServletContext method is called, and the parameter is null. I've tried using #Context on a constructor parameter, I've tried it on my context field, and I've tried it in the getListOfAllUsers method. None of them work.
I just want to configure my servlet (for MySQL database path and user, in this example I'm testing with max-customers-size, which doesn't matter though, because my context is null either way). Is there an easier way to get custom config data into my servlet? I want the user of my resulting war file to be able to supply things like the database port. Why isn't ServletContext working, and if there is an easier way to make my servlet configurable, how do I do that?
Typically a database (DataSource) for Servlet is configured via JNDI (the definition exists on the server JNDI context, and the webapp JNDI context contains a hardcoded reference to the server level location)
Your server level will typically have an XML that defines the DataSource as a org.eclipse.jetty.plus.jndi.Resource against the server level context.
And your webapp's WEB-INF/web.xml contains the <resource-ref> back to that server level location.
Your code then uses the InitialContext on JNDI to access this already defined DataSource.
This has the added bonus that the datasource can be any JDBC compatible implementation, and even include complex configurations like a Connection pool implementation (eg: c3p0) in front of your JDBC DataSource.
For unit testing, you'll set it up like this ...
JNDI Lookup Failing For Embedded Jetty Server
For standard webapp deployment in a standalone Jetty container, you'll set it up like this ...
Declaring JNDI Resources
Related
I am using the restlet routing APIs like
http://localhost:8080/www.example.com/hello/ping
But I don't know how to use this type of method:
/{projectName}/{wallName}
that I have seen in
Restlet routing nightmare?
Could anyone tell me
1.What is the best practice of using Restlet Routing?
2.How to implement /{projectName}/{wallName} in java?
3.How to get the value of projectName from this API?
In fact, there are several part within a Restlet application. Classically, this application is accessible through a Restlet component that can be created as described below:
Standalone mode (outside an application server)
Component component = new Component();
component.setName("My component");
component.getServers().add(Protocol.HTTP, 8182);
MyApplication application = new MyApplication();
// To attach application on /www.example.com
component.getDefaultHost().attach("www.example.com", application);
// To attach application on /
component.getDefaultHost().attachDefault(application);
component.start();
Container mode (servlet support). You can use the extension ext.servlet for this use case. A front servlet is provided that automatically wraps a component. You only have to specify the class of your application implementation, as described below:
<!-- Application class name -->
<context-param>
<param-name>org.restlet.application</param-name>
<param-value>
packageName.MyApplication
</param-value>
</context-param>
<!– Restlet adapter –>
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>
org.restlet.ext.servlet.ServerServlet
</servlet-class>
</servlet>
<!– Catch all requests –>
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
<!-- or -->
<!-- url-pattern>/www.example.com/*</url-pattern -->
</servlet-mapping>
You can now implement the Restlet application. For this implement, a class that extends Application. The routing must be defined within its method createInboudRoot, as described below:
public MyApplication extends Application {
#Override
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/{projectName}/{wallName}", MyServerResource.class);
return router;
}
}
As you can see, a server resource is attached for the path /{projectName}/{wallName}. This server resource is responsible to handle the request. A sample of implementation is described below:
public class MyServerResource extends ServerResource {
#Get
public Representation handleGet() {
String projectName = getAttribute("projectName");
String wallName = getAttribute("wallName");
(...)
}
}
Hope it helps you,
Thierry
this is my first time that I work on a Java project that use HttpServlet.
So I know that an HttpServlet is a program that run on a Web Application server and act as a middle layer between a request coming from a Web browser or other HTTP client and databases or applications on the HTTP server. So the servlet extend the competence of my application server.
I have some doubt to understand how exactly work this servlet founded into my project, into web.xml file I found this configuration:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>My Project</display-name>
<listener>
<listener-class>it.sistinf.ediweb.quartz.QuartzListener</listener-class>
</listener>
<servlet>
<servlet-name>edimon</servlet-name>
<servlet-class>it.sistinf.ediweb.monitor.servlets.Monitoraggio</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>edimon</servlet-name>
<url-pattern>/edimon.do/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/logon.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>displaytag</taglib-uri>
<taglib-location>/WEB-INF/displaytag-11.tld</taglib-location>
</taglib>
</web-app>
So reading some documentation it seem to understand that I have to tell the servlet container (or application server) what servlets to deploy, and what URL's to map the servlets to.
In the previous case I am configuring a servlet named edimon implemented by the Monitoraggio class.
Then it is mapped the servlet to a URL or URL pattern. In this case the edimon servlet is mapping with the /edimon.do/* URL pattern. So when it is called something that match with the previous pattern the edimon servlet is performed.
Then into my Monitoraggio class that implement the HttpServlet I found the service() method:
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
LoggerMDC.setup(req, res);
Logger logger = (Logger) Logger.getStdLogger(Monitoraggio.class); // do not declare 'logger' as static field in order to work with MDC
String service = req.getParameter("serv");
char serviceId = Utility.getServizio(req.getParameter("serv"));
if (checkSession(req, serviceId) == false) {
gotoPage(ConfigurationFactory.getPropertiesPages().getProperty("pagina_errore_session"), req, res);
return;
}
LoggerWatch loggerWatch = new LoggerWatch(Monitoraggio.class, Long.valueOf(System.getProperty(Constants.Keys.CONFIG_STATS_WARNING_THRESHOLD, String.valueOf(LoggerWatch.DEFAULT_WARNING_THRESHOLD))).longValue());
if (logger.isTraceEnabled())
logger.trace("lanciaServizio() | logger threshold: " + loggerWatch.getWarningThreshold());
loggerWatch.start();
loggerWatch.info(new StringBuffer("service() | servizio: [").append(service).append("] | service start").toString());
String paginaDaLanciare = lanciaServizio(serviceId, req, res);
String executionTime = loggerWatch.getInfoTime();
//Modifica per export
if (req.getSession().getAttribute("export") == null) {
gotoPage(paginaDaLanciare, req, res);
}
loggerWatch.info(new StringBuffer("service() | servizio: [").append(service).append("] | [").append(executionTime).append("] after forward to ").append(paginaDaLanciare).toString(), true);
loggerWatch.stop();
req.getSession().removeAttribute("export");
req.getSession().removeAttribute("stringaXML");
req.getSession().removeAttribute("downbyte");
return;
}
Reading on the documentation it receives standard HTTP requests from the public service method and dispatches them to the doXXX methods defined in this class
So what exatly do this method? I can't understand how the servlet load the JSP
The documentation you read describes what the service() method of HttpServlet does by default. Since your servlet overrides the service() method and provides a different implementation, it doesn't do that anymore. Instead, it does... what the code in the method does.
A servlet doesn't "load a JSP". I don't see how JSPs have any relation to the servlet code you posted. Maybe gotoPage() does tell the container to forward the request to a JSP. You should look at the documentation and/or code of that method to know what it does.
What is the difference between loading context in context param and loading it in init-param of Dispatcher Servlet.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
vs
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value> /WEB-INF/mvc-config.xml </param-value>
</init-param>
What i understood is context-param is loaded by context listener and should only contain middle tier beans. Where as Dispatcher Servlet in its init method should load web tier beans. Is this understanding correct? Why do we load 2 things seperately?
<context-param>
Is written outside <Servlet> tag and is inside <webapp> tag.
The values decalred will be available to the whole application
Any servlet in the application (declared in the web.xml) can access the values
So we use this when we want to share the the same set of values across the servlet in the application such as Data base configuration details.
You can use public String getInitParameter(String name) method of ServletContext interface to get value.
getServletContext() method of ServletConfig interface returns the object of ServletContext.
getServletContext() method of GenericServlet class returns the object of ServletContext.
Example 1 : ServletContext application=getServletConfig().getServletContext();
Example 2 : ServletContext application=getServletContext();
<init-param> .
Is written inside <Servlet> tag.
The values declared will be available only to the servlet.
You can use public String getInitParameter(String name) method of ServletConfig interface to get value.
getServletConfig() method of Servlet interface returns the object of ServletConfig.
Example : ServletConfig config=getServletConfig();
In the context-param "contextConfigLocation" you should include your application contexts, as you have already said middle tier beans, like: services, datasource...
The Spring DispatcherServlet will look for config files in WEB-INF/servletName-servlet.xml. Using the init-param you can change this default behaviour. The servlets contexts (web contexts) are isolated but might hold the application contexts as parent. You can use both or one of them independently.
I've got: trivial Spring MVC sample app. I configure DispatcherServlet to handle all requests which start with dispatcher/.
Problem: After deploying to Tomcat, if I try to go to localhost:8080 page I get The requested resource (/) is not available.. But I can go through localhost:8080/dispatcher path.
Questions:
Why does simple test works if we do mockMvc.perform(get("/")) instead of mockMvc.perform(get("/dispatcher"))?
Code:
web.xml:
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/dispatcher/*</url-pattern>
</servlet-mapping>
Controller:
#Controller
#RequestMapping("/")
public class HelloController {
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("message", "Hello world!");
return "hello";
}
}
Test:
#Test
public void simple() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(model().attribute("message", "Hello world!"))
.andExpect(view().name("hello"));
}
Problem: After deploying to Tomcat, if I try to go to localhost:8080
page I get The requested resource (/) is not available.. But I can go
through localhost:8080/dispatcher path.
Accessing your controller from the Servlet Container's perspective - what you're doing when you type localhost:8080/dispatcher - requires a lot of information in the url path. For example, your HelloController is
configured to be handle by the mvc-dispatcher Servlet
mvc-dispatcher Servlet is declared in a web application (defined by your web.xml)
there could be multiple Servlets in your web application
the web application is deployed to your Servlet container (Tomcat)
there could be multiple web applications in the Servlet Container
There's lots of ambiguity in resolving a url when you take all this into consideration. As #san krish pointed out, and assuming you've deployed your application to Tomcat's root context, you can force everything through mvc-dispatcher and map it to /* as default, and end up serving your HelloController from localhost:8080/.
Why does simple test works if we do mockMvc.perform(get("/")) instead
of mockMvc.perform(get("/dispatcher"))?
Accessing your controller from mockMvc in your test is pretty localized. Depending on how your test was set up, a MockMvc instance was created either from:
MockMvcBuilders.standaloneSetup(controller) - here your controller is passed directly to the test for testing, therefore MockMvc knows nothing about a mvc-dispatcher and it's "/dispatcher" path.
MockMvcBuilders.webAppContextSetup(webApplicationContext) - here, the test class is annotated with a #ContextConfiguration that points to your "mvc-dispatcher" xml or #Configuration class. In this situation, MockMvc would be acting on everything localized under "mvc-dispatcher" so there's no need to reference the "dispatcher" in the path.
In the web.xml map the wildcard entry
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
It will pass all in-coming requests to the dispatcher servlet
For a web application I make use of JSF 1.2 and Facelets.
The problem is that we now do the initialisation via a singleton pattern and that takes about 5-15 seconds because it read in data files (we are not using a database). This happens when the first user browses to the corresponding web page (the 2nd and other users don't have this delay).
I would like to have this singleton initialised right after deployment. How can I do this? I've tried to add an application bean but it does not get called. I've also tried to add a servlet as followings:
<servlet>
<description>MyApplicationContextListener Servlet</description>
<display-name>MyApplicationContextListener Servlet</display-name>
<servlet-name>MyApplicationContextListener</servlet-name>
<servlet-class>mydomain.beans.MyApplicationContextListener</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<listener>
<listener-class>mydomain.beans.MyApplicationContextListener</listener-class>
</listener>
with the following code:
package mydomain.beans;
import javax.servlet.ServletContextEvent;
public class MyApplicationContextListener {
public void contextInitialized(ServletContextEvent event) {
System.out.println("MyApplicationContextListener.contextInitialized started");
}
public void contextDestroyed(ServletContextEvent event) {
System.out.println("MyApplicationContextListener.contextInitialized stopped");
}
}
An example including changes needed in web.xml and/or faces-config.xml would be nice!
How about using a ServletContextListener ? Its contextInitialized(..) method will be called at the moment the context is initialized. It's mapped in web.xml like this:
<listener>
<listener-class>com.example.MyServletContextListener</listener-class>
</listener>
Also, (not sure this would work), you can configure your faces-servlet to be loaded on startup.:
<load-on-startup>1</load-on-startup>
Clarification: For the listener approach, your listener must implement the ServletContextListener:
public class MyServletContextListener implements ServletContextListener { .. }