WebAppppppps
WebApps (mostly java/tomcat related)
Also see my Java Blog and my C# BlogIncrease Tomcat Windows Service memory
--JvmMs Initial memory pool size in MB. (Not used in exe mode.)
--JvmMx Maximum memory pool size in MB. (Not used in exe mode.)
Run the US "Update Service" option
C:\Program Files\Tomcat9\bin>tomcat9.exe //US//Tomcat9 --JvmMs=1024 --JvmMx=1024 --JvmSs=1024
then verify by opening tomcat9w.exe
then restart the service
then verify via the manager webapp
http://localhost:8080/manager/status/all
Careful with setting culture!!!
Setting [assembly: AssemblyCulture("ca")]can cause problems for visual studio finding the dll
sometimes in its specified via AssemblyInfo.cs
SharedLibTest.exe
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly
'SharedLib, Version=2016.7.25.1, Culture=ca, PublicKeyToken=null' or one of its dependencies.
The system cannot find the file specified.
at SharedLibTest.Program.Main(String[] args)
H:\Visual Studio 2013\Projects\SharedLib\SharedLibTest\bin\Debug>
According to msdn :
Putting this attribute on an assembly and using something other than the empty string ("") for the culture name will make this assembly look like a satellite assembly, rather than a main assembly that contains executable code. Labeling a traditional code library with this attribute will break it, because no other code will be able to find the library's entry points at runtime.
Translucent background image on simple html w/style
<html><body style='position: relative;'>
<div id='img_background'
style='position:absolute; width:100%; height:100%; opacity:.2; background:url(bg.png) center center; background-repeat:no-repeat;'></div>
This page has an image background (via a simple div above)
<br/>
The text is not translucent, however the image is (via the opacity setting)
</body></html>
Pull from web.config file in aspx
<asp:SqlDataSource ID="MetricEntryFrequencyDataSource" runat="server"ConnectionString="<%$ ConnectionStrings:MetricConnectionString %>"
ProviderName="<%$ ConnectionStrings:MetricConnectionString.ProviderName %>"
SelectCommand="SELECT FREQ_ID, FREQ_DESC,'_',' ') FROM MetricEntry.FREQUENCY "></asp:SqlDataSource>
C# ASP.NET Web Page Life-Cycle Stages
https://msdn.microsoft.com/en-us/library/ms178472.aspx
Pages also support automatic event wire-up,
meaning that ASP.NET looks for methods with particular names
and automatically runs those methods
when certain events are raised.
If @Page directive AutoEventWireup attr is set to true,
page events are automatically bound to methods
that use the naming convention of
Page_event (ex: Page_Load, Page_Init, etc)
- Page_PreInit
- Page_Init
- Page_InitComplete
- Page_PreLoad
- Page_Load
- Page_LoadComplete
- Page_PreRender
- Render
- Page_Unload
JSP - show/display static variable/field/string from servlet
package vids;public class MainServlet extends HttpServlet{
public static final String VidDirUnderRootDir="Vids";
public static String getVidDirUnderRootDir() {
return VidDirUnderRootDir;
}
...
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page import="vids.MainServlet" %>
<!doctype html><html><head><title>Vids</title>
</head>
<body>
Folder is ${MainServlet.VidDirUnderRootDir}
</body></html>
c# pulls variables into aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PagePullVariable.aspx.cs" Inherits="WebAppTest.PagePullVariable" %>
<%@ Import Namespace="SharedLib" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%=S1%><br />
<%=S2%><br />
<%=S3%><br />
<%=UtilsDatabase.ConnectionString_INDOT_Oper %>
</div>
</form>
</body>
</html>
<%@ Import Namespace="SharedLib" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%=S1%><br />
<%=S2%><br />
<%=S3%><br />
<%=UtilsDatabase.ConnectionString_INDOT_Oper %>
</div>
</form>
</body>
</html>
using SharedLib;
namespace WebAppTest {
public partial class PagePullVariable : System.Web.UI.Page {
public string S1 = "S1 is a public string";
public static string S3 = "S3 public static string";
private string s2="S2 is private but has a public function";
public string S2 { get { return s2; } }
protected void Page_Load(object sender, EventArgs e) { S1 = UtilsClass.GetMethodName(); }
protected void Page_LoadComplete(object sender, EventArgs e) { S1 = UtilsClass.GetMethodName(); }
protected void Page_PreRender(object sender, EventArgs e) { S1 = UtilsClass.GetMethodName(); }
/// <summary>
/// this does not show on page (since this is AFTER the page was rendered to the browser)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_UnLoad(object sender, EventArgs e) { S1 = UtilsClass.GetMethodName(); }
}
}
Java Windows Authentication (with WAFFLE)
Tomcat Negotiate (Kerberos + NTLM) authenticator to Waffle 1.3 for Tomcat 6:Download/unzip Waffle
copy these jars from waffle/bin to tomcat/lib:
waffle-tomcat8
waffle-jna ...Tomcat Negotiate Authenticator
jna-platform ...JNA platform-specific API
jna ...Java Native Access might use the dll below
guava ...a google api jar
slf4j-api ...logging I think
copy this dll to tomcat/bin
Waffle.Windows.AuthProvider.dll
app's context.xml (or in server.xml for all app's)
<Context>
<Valve className="waffle.apache.NegotiateAuthenticator" principalFormat="fqn" roleFormat="both" />
<Realm className="waffle.apache.WindowsRealm" />
</Context>
app's web.xml
this adds user’s domain groups as tomcat "roles"
<security-role>
<role-name>Everyone</role-name>
</security-role>
this requires authen for entire website:
<security-constraint>
<display-name>Waffle Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Everyone</role-name>
</auth-constraint>
</security-constraint>
Test:
Ensure IE Integrated Windows Authentication is enabled.
Tools->Options->Advanced_tab->Security->Enable Integrated Win Authen (...for Intranet Zone)
Restart Tomcat: http://localhost:8080
if prompted w/logon popup, its cuz localhost is not in _Intranet Zone (so: 401 Unauthorized) Note: fqdn's are detected/authenticated automatically!
Verify:
logs will show successful logon as:
logged in user: dblock-green\dblock (S-1-5-21-345183-1395134217-4167419351-1000)
group: dblock-green\None
group: Everyone
group: dblock-green\HelpLibraryUpdaters
group: dblock-green\HomeUsers
group: BUILTIN\Administrators
...
group: NT AUTHORITY\INTERACTIVE
group: S-1-5-5-0-442419
group: LOCAL
group: NT AUTHORITY\NTLM Authentication
group: Mandatory Label\Medium Mandatory Level
successfully logged in user: dblock-green\dblock
if ur computer is a member of A/D domain, u would see domain groups
this works for Negotiate protocol, chooses Kerberos vs. NTLM and supports NTLM POST.
So, its like IIS's Integrated Windows authentication!!!
Troubleshooting (Tomcat) - Enable waffle logging.
Add this to Tomcat\conf\logging.properties
############################################################
# Windows Authentication logging via WAFFLE
############################################################
waffle.servlet.NegotiateSecurityFilter.level = FINE
waffle.servlet.spi.SecurityFilterProviderCollection.level = FINE
waffle.servlet.spi.NegotiateSecurityFilterProvider.level = FINE
waffle.servlet.spi.BasicSecurityFilterProvider.level = FINE
Restart Tomcat and review logs\Catalina*.log.
https://github.com/dblock/waffle
JNDI
Sample Servlet Code:
public void testDataSourceConnection(String dsName,PrintWriter pw) throws ServletException{
pw.println("<p>Testing connection to context.xml dataSource: "+dsName);
DataSource dsSpt=getDataSource(dsName);
try{Connection conn=dsSpt.getConnection(); conn.close();
pw.println("<p>Testing connection to context.xml dataSource completed successfully to "+dsName);
}catch(SQLException se){
GlobalErrorHandler.handleSqlException(se," Error connecting to "+dsName);
}
}
public DataSource getDataSource(String jndiName) throws ServletException{
try{Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:comp/env");
return (DataSource)envContext.lookup(jndiName);
}catch(NamingException ne){String err="JNDI Naming err:"+ ne.getMessage();
MainClass.logIt(err);
throw new ServletException(err);
}
}
public static void handleSqlException(SQLException e, String msg) throws ServletException{
if(msg == null) msg="";
String err="SQL_Error:"+ e.getMessage()+" (SQL_State:"+e.getSQLState()+") "+MainClass.SystemLineSeparator+msg;
MainClass.logIt(err); e.printStackTrace(); throw new ServletException(err);
}
browser cache
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="Expires" content="0"/>
<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="Expires" content="0"/>
Sample META-INF/context.xml:
Note samples included for oracle 11G and MS SQL Server 2005+
<Context>
<Resource name="jdbc/DWTARGET" auth="Container" type="javax.sql.DataSource"
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
username="dwtargetuser" password="blaa"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@minoraP05vw:1585:inmindw" />
<Resource name="jdbc/SPT" auth="Container" type="javax.sql.DataSource"
validationQuery="select 1"
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
username="sptuser" password="somepwd"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://minsqlp24vw:1433/INMINAPP01;instance=p24vwminprod" />
</Context>
Note 1: the JTDS driver is MUCH faster than the MS jdbc driver.
http://sourceforge.net/projects/jtds/postdownload?source=dlp
Note 2: The "validationQuery" parm/attr is used for the ms sql JNDI datasource
because the ms sql server JTDS driver does NOT support for the JDBC4.0 isValid() method.
java.lang.AbstractMethodError
at net.sourceforge.jtds.jdbc.JtdsConnection.isValid(JtdsConnection.java:2833)
See: https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html
because the ms sql server JTDS driver does NOT support for the JDBC4.0 isValid() method.
java.lang.AbstractMethodError
at net.sourceforge.jtds.jdbc.JtdsConnection.isValid(JtdsConnection.java:2833)
**************************************************
include vs jsp:include
include vs jsp:include<%@ include file="myHeader.jspf" %>
static include (resolved at compile time)
like copy-pasting exact content of included file
Note: .jspf are static JSP fragments (partial pages), and cannot get parms like jsp's can
<jsp:include page="myParialPage.jsp" />
dynamic include (resolved at execution time in it's own pageContext)
...allowing parms to be passed/read ${param["MY_PARM"]}:
<jsp:include page="..." >
<jsp:param name="MY_PARM" value="SomeVal"/>
</jsp:include>
So do NOT include the html and body header elements in a jsp.included jsp.
If child page resolves its URLs relative to itself, consider including via dsp:include
<dsp:include otherContext="/someOtherWebApp" page="/ChildPage.jsp"/>
ChildPage.jsp page is embedded in the parent page.
otherContext attribute include pages from other Web apps!!!
(w/o requiring the context path be included in the web.xml)
See also: <jsp:forward page="/main.jsp" />
Note if data has already been returned to a client, jsp:forward gens IllegalStateException
Note: if you include the jsp from various web paths/folders,
then you might need to reference the app context path like so:
<form action="${pageContext.request.contextPath}/MyReport">
**************************************************
forward vs redirect
jsp forward - The pathname cannot extend outside the current servlet context (aka webapp)but HttpServletResponse.sendRedirect can sent to another webapp
however
If you want to forward to a different web app in the same tomcat instance, you can:
in its META-INF/context.xml set <Context crossContext="true" />
getServletContext().getContext("/app").getRequestDispatcher("f.jsp").forward(..);,
where app is the name of the other application.
**************************************************
Simple/Fun Error Handler!
POJO Bean (holds error/exception info)
package dashboard;import javax.servlet.http.HttpSession;
/**
* Simple POJO Bean shows error details. Looks for customAttemptInfo in Session for custom pre-error info.
* @author mdockery
*/
public class ErrorBean{
/**
* field used to show more info about what attempt is being made w/in the app before/if an error occurrs
*/
public static String attemptInfoFieldName="customAttemptInfoString";
public Integer statusCode;
public String requestUri, servletName, exceptionName, msg, attemptInfo, stackTrace;
public static String getAttemptInfoFieldName(){
return attemptInfoFieldName;
}
public ErrorBean() {}
//session custom attempt info (if the developer chooses to populate it)
public static void clearSessionAttemptString(HttpSession ses){ ses.setAttribute(attemptInfoFieldName,"--");}
/**
* puts custom text message describing what is about to be attempted into session (for error page to display if it fails)
* @param ses session obj
* @param attemptInfo custom descriptive string text
*/
public static void setSessionAttemptString(HttpSession ses, String attemptInfo){
ses.setAttribute(attemptInfoFieldName,attemptInfo);
}
public static String getSessionAttemptString(HttpSession ses){
String attemptInfo=(String)ses.getAttribute(attemptInfoFieldName);
return attemptInfo;
}
// getters/setters
public String getAttemptInfo(){return attemptInfo;}
public void setAttemptInfo(String attemptInfo){ this.attemptInfo=attemptInfo;}
public Integer getStatusCode(){ return statusCode;}
public void setStatusCode(Integer statusCode){ this.statusCode=statusCode;}
public String getRequestUri(){ return requestUri;}
public void setRequestUri(String requestUri){ this.requestUri=requestUri;}
public String getServletName(){ return servletName;}
public void setServletName(String servletName){ this.servletName=servletName;}
public String getExceptionName(){ return exceptionName;}
public void setExceptionName(String exceptionName){ this.exceptionName=exceptionName;}
public String getMsg(){return msg;}
public void setMsg(String msg){ this.msg=msg;}
public static void setAttemptInfoFieldName(String attemptInfoFieldName){ErrorBean.attemptInfoFieldName=attemptInfoFieldName;}
public String getStackTrace(){ return stackTrace;}
public void setStackTrace(String stackTrace){ this.stackTrace=stackTrace;}
}
Show app context String ArrayList on jsp, loaded from init method of servlet:
public class RefreshRunServlet extends HttpServlet{private static final long serialVersionUID=1L;
Context initContext; Context envContext; DataSource ds_DWSOBIEE; public void init(ServletConfig config) throws ServletException{
try{initContext=new InitialContext();
envContext =(Context)initContext.lookup("java:/comp/env");
ds_DWSOBIEE =(DataSource)envContext.lookup("jdbc/DWSOBIEE");
ServletContext app = config.getServletContext();
app.setAttribute("AREAS",getSubjectAreas(ds_DWSOBIEE, this.getClass().getName()));
}catch(NamingException ne){System.out.println("JNDI Naming err:"+ ne.getMessage());}
}
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
...
---------------------------------------------
<%@ page errorPage="/GlobalErrorHandler" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!doctype html><body>
Items:
<c:forEach items="${AREAS}" var="area">
${area}<br>
</c:forEach>
</body></html>
Simple Servlet (populate bean above for JSP display/output):
package dashboard;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GlobalErrorHandler extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {processError(request, response);}
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {processError(request, response);}
private void processError(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
MainWindow.logIt(req.getRemoteAddr()+" "+ req.getRemoteHost()+" called GlobalErrorHandler (RemoteUser:"+req.getRemoteUser()+")");
ErrorBean errBean=new ErrorBean();
Throwable throwable = (Throwable) req.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer) req.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) statusCode = 0;
errBean.setStatusCode(statusCode);
String servletName = (String) req.getAttribute("javax.servlet.error.servlet_name");
if (servletName == null) servletName = "Unknown";
String requestUri = (String) req.getAttribute("javax.servlet.error.request_uri");
if (requestUri == null) requestUri = "Unknown";
errBean.setRequestUri(requestUri);
String err="?";
switch(statusCode){
case 401: err="Unauthorized."; break;
case 403: err="Forbidden."; break;
case 404: err="Page not found."; break;
case 405: err="Method Not Allowed."; break;
default: break;
}
if(statusCode==500){err="Application Error.";
errBean.setServletName(servletName);
try{errBean.setMsg(throwable.getMessage());}catch(Exception e){errBean.setMsg("Perhaps a JSP error...");}
try{errBean.setExceptionName(throwable.getClass().getName());}catch(Exception e){errBean.setExceptionName("Perhaps a JSP error...");}
try{StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
errBean.setStackTrace(sw.toString()); // stack trace as a string
}catch(Exception e){}
}
errBean.setMsg(err+requestUri);
if(req.getSession().getAttribute(ErrorBean.attemptInfoFieldName)==null)
req.getSession().setAttribute(ErrorBean.attemptInfoFieldName,err+requestUri);
req.setAttribute("errBean",errBean);
MainWindow.logIt("GlobalErrorHandler was provided this error:"+errBean.getMsg()+" "+errBean.getExceptionName()+" "+errBean.getAttemptInfo());
MainWindow.logIt("Trace:"+errBean.getStackTrace());
MainWindow.logIt("GlobalErrorHandler is about to forward to the GlobalError.jsp");
getServletContext().getRequestDispatcher("/GlobalError.jsp").forward(req,res);
}
/**
* Print/Log the SQL error details via STDOUT and throw ServletException
* @param e the exception
* @param customOptionalInfo any custom message
* @throws ServletException for display on the error jsp page
*/
public static void handleSqlException(SQLException e, String customOptionalInfo) throws ServletException{
if(customOptionalInfo == null) customOptionalInfo=" - No customOptionalInfo included" ;
String err="SQL_Error:"+ e.getMessage()+" (SQL_State:"+e.getSQLState()+") "
+MainWindow.SystemLineSeparator+customOptionalInfo;
MainWindow.logIt(err); e.printStackTrace(); throw new ServletException(err);
}
}
GlobalError.jsp
<%@ page isErrorPage="true" %><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ page import="dashboard.ErrorBean" %>
<head><title>Global_Error Page (${errBean.statusCode})</title>
<link rel="stylesheet" href="style.css" />
</head><body>
<h3>We are sorry but the following ${errBean.statusCode} error has occurred</h3>
<ul>
<li/> servletName.....: ${errBean.servletName}
<li/> exceptionName...: ${errBean.exceptionName}
<li/> statusCode......: ${errBean.statusCode}
<li/> requestUri......: ${errBean.requestUri}
<li/> Message.........: ${errBean.msg}
</ul>
<hr/><h2> Custom Attempt Info:</h2>
<textarea rows="10" cols="150"> ${customAttemptInfoString} </textarea>
<c:if test="${errBean.statusCode == 500}"> <hr/>
<h2> Stack Trace (if 500 App Error):</h2>
<textarea rows="10" cols="150"><pre> ${errBean.stackTrace} </pre></textarea>
</c:if>
</body>
WEB-INF/web.xml deployment descriptor
...<servlet>
<servlet-name>GlobalErrorHandler</servlet-name>
<servlet-class>reports.GlobalErrorHandler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GlobalErrorHandler</servlet-name>
<url-pattern>/GlobalErrorHandler</url-pattern>
</servlet-mapping>
<error-page> <error-code>404</error-code>
<location>/GlobalErrorHandler</location>
</error-page>
<error-page> <exception-type>javax.servlet.ServletException</exception-type>
<location>/GlobalErrorHandler</location>
</error-page>
...
</web-app>
Some class which is about to attempt something
...
StackTraceElement el=Thread.currentThread().getStackTrace()[1];
String thisClass=el.getClassName();
String thisMethod=el.getMethodName();
ErrorBean.setSessionAttemptString(ses,thisClass+"."+thisMethod+" is attempting DWTARGET SQL: "+SystemLineSeparator+sql);
Simple JSP error handling
</head><body><c:catch var="err">
${infoBean.yyyyy}
</c:catch>
<c:if test="${not empty err}">
JSP Error: ${err}
</c:if>
...
**************************************************************
Simple db webapp (64bit java, 64bit tomcat, 64bit odbc driver)
setx /M JAVA_HOME "C:\Program Files\Java\jdk1.8.0_40"C:\Program Files\tomcat8\lib\ojdbc6.jar
META-INF/context.xml
<Context><Resource name="jdbc/EMDB" auth="Container" type="javax.sql.DataSource"
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
username="metricuser" password="metriblabla"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@plotoraQ05PW:1545:pindotdev"
/>
</Context>
WEB-INF/web.xml
<?xml version="1.0" encoding="ISO-8859-1" ?><web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>DB App</display-name>
<description>DB App</description>
<servlet>
<servlet-name>Main</servlet-name>
<servlet-class>db.Main</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Main</servlet-name>
<url-pattern>/Main</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>Main</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>MainPage</servlet-name>
<jsp-file>/MainPage.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>MainPage</servlet-name>
<url-pattern>/MainPage</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>MainPage</welcome-file>
</welcome-file-list>
</web-app>
servlet
package db;import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
public class Main extends HttpServlet{
private static final long serialVersionUID=1L;
Context initContext; Context envContext; DataSource ds; Connection conn=null;
public void init() throws ServletException{
try{initContext = new InitialContext();
envContext = (Context)initContext.lookup("java:/comp/env");
ds = (DataSource)envContext.lookup("jdbc/EMDB");
}catch(NamingException ne){System.out.println("JNDI Naming err:"+ ne.getMessage());}
}
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<h1>attempt conn</h1>");
try{conn = ds.getConnection();
String sql="select MEASURE_ID from MEASURES where MEASURE_ID=140";
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery(sql);
out.println("<h1>GOT conn</h1>");
while(rs.next()) {
out.println("<h1>"+rs.getString(1)+"</h1>");
}
out.println("<h1>GOT results</h1>");
}catch(SQLException sq){System.out.println("SQL err:"+ sq.getMessage());
}finally{try{conn.close();}catch(SQLException ss){}}
out.println("<h1>DONE</h1>");
out.flush();
}
}
http://localhost:8080/DB/
attempt conn
GOT conn
140
GOT results
DONE
**************************************************************
Simple JSP (which pulls from a servlet loaded POJO bean)
//The servlet doGet method:
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{ //populate info, top hoverHelp, and bottom url/imageInfoHelper.getCell8A_AwardTotalDollarsConsultant(infoBean,"start","enddddd");
infoBean.setCell8A_AwardTotalDollarsConsultantHelp(InfoHelper.helpCell8A_AwardTotalDollarsConsultant); //mouseover hoverHelp text at top of page
infoBean.setCell8A_AwardTotalDollarsConsultantUrl(InfoHelper.urlCell8A_AwardTotalDollarsConsultant); //mouseover helpUrl/image at boottom of page
req.setAttribute("infoBean",infoBean);
getServletContext().getRequestDispatcher("/reports/uniform/MainPage.jsp").forward(req,res);;
}
The simple POJO bean
package reports.uniform;/**
* Simple info bean to show info onto a jsp webpage
* the variables hold info, and any relevant mouse hoverHelp and useful URL/pictures
* @author mdockery
*/
public class InfoBean{
public int cell8A_AwardTotalDollarsConsultant;
public int getCell8A_AwardTotalDollarsConsultant(){
return cell8A_AwardTotalDollarsConsultant;
}
public void setCell8A_AwardTotalDollarsConsultant(int cell8a_AwardTotalDollarsConsultant){
cell8A_AwardTotalDollarsConsultant=cell8a_AwardTotalDollarsConsultant;
}
public String getCell8A_AwardTotalDollarsConsultantHelp(){
return cell8A_AwardTotalDollarsConsultantHelp;
}
public void setCell8A_AwardTotalDollarsConsultantHelp(String cell8a_AwardTotalDollarsConsultantHelp){
cell8A_AwardTotalDollarsConsultantHelp=cell8a_AwardTotalDollarsConsultantHelp;
}
public String getCell8A_AwardTotalDollarsConsultantUrl(){
return cell8A_AwardTotalDollarsConsultantUrl;
}
public void setCell8A_AwardTotalDollarsConsultantUrl(String cell8a_AwardTotalDollarsConsultantUrl){
cell8A_AwardTotalDollarsConsultantUrl=cell8a_AwardTotalDollarsConsultantUrl;
}
public String cell8A_AwardTotalDollarsConsultantHelp, cell8A_AwardTotalDollarsConsultantUrl;
public InfoBean() {}
}
The JSP which uses JSTL tags and the loaded bean getter's (loaded from servlet above)
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html><head>
<c:set var="title" value="Uniform Report" />
<title>${title}</title>
</head><body>
<c:set var="now" value="<%=new java.util.Date()%>" />
<c:set var="rowHeight" value="10" />
<table><!-- The header table -->
<tr>
<td><h1>${title}</a></h1>
<h2>As of <fmt:formatDate pattern="yyyy-MM-dd_HH:mm (E)" value="${now}" /> </h2></td>
<td><textarea rows="6" cols="110" id="hoverHelp">Hover below to see Metric Description/Help/Tips</textarea></td>
</tr><table>
<script>
function hoverHelper(pID, pHtml, url) {
pHtml=pHtml.replace(/~/g,'\n');
document.getElementById(pID).value=pHtml;
if(!url) url="LOGO.jpg";
document.getElementById("hoverImageURL").src = url;
}
function hoverClear(pID) {
document.getElementById(pID).value="";
document.getElementById("hoverImageURL").style.backgroundImage = "none";
} </script>
<hr/>
<table border=1><!-- The metrics table -->
<tr> <!-- Report Row 1 -->
<td onmouseover='hoverHelper("hoverHelp",
"${infoBean.cell8A_AwardTotalDollarsConsultantHelp}",
"${infoBean.cell8A_AwardTotalDollarsConsultantUrl}")'>
${infoBean.cell8A_AwardTotalDollarsConsultant}
</td>
</tr>
</table>
<iframe id="hoverImageURL" src="" width='95%' height='400px' ></iframe>
</body></html>
JSP access req parameters/parms via jstl
${param["spid"]}Image icon (favicon.ico)
you can have your webapp icon be a png or gif (specified at the page level)<html><head><title>Doc's Daily Data Dashboard</title>
<link href="favicon.png" type="image/png" rel="shortcut icon" />
<link href="favicon.png" type="image/png" rel="icon"/>
</head><body>
or
simply use favicon.cc to gen a generic favicon.ico file for your app-wide web app root called favicon.ico
or use http://icoconvert.com/
jsp javascript line continuation char is the backslash \
...<td onmouseenter='showHelp("(amtPaymentInprogressDbePscs: \
${infoBean.amtPaymentInprogressDbePscs} + amtPaymentInprogressDbeDss:${infoBean.amtPaymentInprogressDbeDss}) \
/ ( amtPaymentInprogressPscs........:${infoBean.amtPaymentInprogressPscs} \
amtPaymentInprogressDss...:${infoBean.amtPaymentInprogressDss}")'>
<fmt:formatNumber type="PERCENT" value="${(infoBean.amtPaymentInprogressDbePscs + infoBean.amtPaymentInprogressDbeDss)/(infoBean.amtPaymentInprogressPscs + infoBean.amtPaymentInprogressDss)}" /></td>
...
html javascript line continuation is sometimes the plus sign +
<span id='click_me'onclick="document.getElementById('MyLabel').textContent='thank you for clicking'; +
setTimeout(function(){alert('thanks');},2000);">
click me</span>
SetTimeOut example in JSP
<%@ page errorPage="/GlobalErrorHandler" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ page import="mappings.MappingBean" %>
<!doctype html><html><head><title>Mappings</title>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="Expires" content="0"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
function updateFrame(){
document.getElementById('MAPPINGS_FRAME').src = 'please_wait.png';
var module=document.getElementById('MODULE').value;
var mapping=document.getElementById('MAPPING').value;
var url='MappingRunServlet?MODULE='+module+'&MAPPING='+mapping;
//alert("url is " + url);
document.getElementById('MAPPINGS_FRAME').src = url;
}</script>
</head><body>
<h2>Click the button to Run ${param["MAPPING"]}. </h2>
<table><tr align="center">
<td width='100px'>
<input type="image" id='RUN_BUTTON' src="button_run.png" id="RUN_BUTTON"
title="Run Mapping ${param["MAPPING"]}"
onclick="document.getElementById('MAPPINGS_FRAME').src='please_wait.png'; setTimeout(function(){ updateFrame(); }, 100);" />
</td>
<td width='150px'>Module: ${param["MODULE"]} <input id='MODULE' type='hidden' value='${param["MODULE"]}'></td>
<td width='500px'>Mapping: ${param["MAPPING"]} <input id='MAPPING' type='hidden' value='${param["MAPPING"]}'></td>
</tr>
</table>
<iframe id="MAPPINGS_FRAME" src="about:blank" style='border:0px;width:99%;height:500px;'></iframe>
<hr/>
<iframe id="PROCESS_FLOWS_FRAME" src="ProcessServlet?MAPPING=${param["MAPPING"]}" style='border:0px;width:99%;height:300px;'></iframe>
<hr/> <h4>Recent Run History:</h4>
<iframe id="MAPPING_HIST_FRAME" src="MappingHistoricalCountsServlet?MAPPING=${param["MAPPING"]}" style='border:0px;width:99%;height:400px;'></iframe>
</body></html>
Reading/Writing files
when reading/writing files via webapp, one method is to use this property for the dir base/path:System.getProperty( "catalina.home" )
===============================================================
Apache Tomcat Windows Authentication
Kerberos (the basis for integrated Windows authentication) requires careful configuration.
The host name used to access the Tomcat server must match the host name in the SPN exactly else authentication will fail. see debug logs for checksum error
The client must be of the view that the server is part of the local trusted intranet.
The SPN (svr principal name) must be HTTP/<hostname> and it must be exactly the same in all the places it is used.
The port number must not be included in the SPN.
ONLY 1 SPN may be mapped to a domain user.
Tomcat must run as the domain user account w/which the SPN has been associated
The domain name is not case sensitive when used in the ktpass command, nor when used in jaas.conf
The domain must be specified when using the ktpass command
There are 4 components to the configuration of the built-in Tomcat support for Windows authentication.
The domain controller,
the server hosting Tomcat,
the web application wishing to use Windows authentication and
the client machine.
ex domain: "DEV.LOCAL" with these members:
win-dc01.dev.local (the DC),
win-tc01.dev.local (Tomcat) and
win-pc01.dev.local (client).
--< DC >-----------------------------------
DC tested running Win08 R2 64-bit Standard (using Win03 functional level on forest & domain)
Create a domain user (to be mapped to the tomcat service)
ex: "tc01" w/password tc01pass
Map the user acnt to an SPN <service class>/<host>:<port>/<service name>
setspn -A HTTP/win-tc01.dev.local tc01
Generate a keytab file Tomcat will use to authenticate itself to DC. It has the spn, user & private key, so protect it accordingly
ktpass /out c:\tomcat.keytab /mapuser tc01@DEV.LOCAL /princ HTTP/win-tc01.dev.local@DEV.LOCAL /pass tc01pass /kvno 0
Create/use a domain user to be used on the client.
ex: "test" w/password testpass
--< Tomcat >-----------------------------------
Tomcat w/Oracle JDK 1.6.0_24 64-bit running as domain user: "tc01@DEV.LOCAL"
Copy the tomcat.keytab file created on the DC to $CATALINA_BASE/conf/tomcat.keytab.
Create the kerberos config file $CATALINA_BASE/conf/krb5.ini specifying the domain, keytab, and ticket encryption:
Note: location can be changed via system property: java.security.krb5.conf
[libdefaults]
default_realm = DEV.LOCAL
default_keytab_name = FILE:c:\apache-tomcat-8.0.x\conf\tomcat.keytab
default_tkt_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96
default_tgs_enctypes = rc4-hmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96
forwardable=true
[realms]
DEV.LOCAL = {
kdc = win-dc01.dev.local:88
}
[domain_realm]
dev.local= DEV.LOCAL
.dev.local= DEV.LOCAL
Create the JAAS login configuration file $CATALINA_BASE/conf/jaas.conf:
Note: location can be changed via system property: java.security.auth.login.config
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required
doNotPrompt=true
principal="HTTP/win-tc01.dev.local@DEV.LOCAL"
useKeyTab=true
keyTab="c:/apache-tomcat-8.0.x/conf/tomcat.keytab"
storeKey=true;
};
com.sun.security.jgss.krb5.accept {
com.sun.security.auth.module.Krb5LoginModule required
doNotPrompt=true
principal="HTTP/win-tc01.dev.local@DEV.LOCAL"
useKeyTab=true
keyTab="c:/apache-tomcat-8.0.x/conf/tomcat.keytab"
storeKey=true;
};
The LoginModule used is a JVM specific one so ensure that the it matches the JVM being used.
The name of the login configuration must match the value used by the authentication valve.
The SPNEGO authenticator will work with any Realm but if used with the JNDI Realm,
by the JNDI Realm uses the user's delegated credentials to connect to the Active Directory.
--< Web App >-----------------------------------
web.xml needs configed to use Tomcat SPNEGO authentication method (rather than BASIC etc.)
Simple JSP if statement
<a href='reports/uniform/Readme.html'>${param["TITLE"]}</a>
<c:if test="${param['REPORT_TYPE']=='STATE'}"> STATE VERSION </c:if>
Logging
log("something"); //will log to catalina.logSystem.out.println("something"); //will log to stdout.txt
Simple ashx (which is like a simple java servlet)
using System;using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace doco.EM.DotNetWeb.F01 {
/// <summary>
/// Summary description for GetRemarks <para/>
/// This is a generic httphandler ashx.cs (like a simple java servlet) <para/>
/// designed to pull a simple string value from db and return it to the http client browser <para/>
/// </summary>
public class GetRemarks : IHttpHandler {
public void ProcessRequest(HttpContext context) {
Tracing.LogMessage("GetRemarks ProcessRequest is running...");
var parm1 = context.Request["parm1"];
var parm2 = context.Request["parm2"];
context.Response.ContentType = "text/plain";
//context.Response.Write("This is output from GetRemarks ashx.cs (similar to servlet)");
string remarks="(NO_COMMENTS)";
if(parm1 != null && parm2 != null) {
string measure_id = parm1;
string asOf_keyDateString = parm2;
Tracing.LogMessage("Getting Remarks for measure_id:" + measure_id+" and asOf_keyDateString:" + asOf_keyDateString);
if(measure_id == null || asOf_keyDateString == null) {
remarks = "null measure_id or asOf_KeyDate parameter";
} else {
remarks = "ID:" + measure_id + " (" + asOf_keyDateString + ") " + getRemarks(measure_id, asOf_keyDateString, context.Application);
}
//Tracing.LogMessage(remarks);
}
context.Response.Write(remarks);
}
public string getRemarks(string measure_id, string asOf_keyDateString, HttpApplicationState app) {
SqlDataSource sqlDSrc = new SqlDataSource();
sqlDSrc.ProviderName = Global.SQL_PROVIDER;
//string connString = WebConfigurationManager.ConnectionStrings["MetricConnectionString"].ConnectionString;
string connString = DBConnection.APP_DotNetWebConnectionString;
sqlDSrc.ConnectionString = connString; //see Web.Config <connectionStrings>
string remarks = "( NO_COMMENTS )", sqlGetRemarks = "select nvl(mh.REMARKS,'(NO_COMMENTS)') remarks from MEASUREACTUALHISTORY mh "
+ " where measure_id=" + measure_id + " and trunc(mh.ASOF_KEYDATE)=to_date('" + asOf_keyDateString + "','MONDD_YYYY') ";
app["ERR_PAGE_OUT_MSG"] = sqlGetRemarks;
sqlDSrc.SelectCommand = sqlGetRemarks;
try{DataView SQLResultSet = (DataView)sqlDSrc.Select(DataSourceSelectArguments.Empty);
foreach(DataRow SQLResultSetRow in SQLResultSet.Table.Rows) {
remarks=SQLResultSetRow["remarks"].ToString();
return remarks;
}
} catch(Exception e) {
Tracing.LogMessage(sqlGetRemarks+ " ______Error:"+ e.Message);
remarks = e.Message;
Tracing.LogMessage(e.StackTrace);
}
return remarks;
}
public bool IsReusable {get {return false;}}
}
}
Comments
Post a Comment