Search Results

Search found 2593 results on 104 pages for 'meta knight'.

Page 102/104 | < Previous Page | 98 99 100 101 102 103 104  | Next Page >

  • error echo id when i want to echo id for edit

    - by Prasanta Baidya
    I have a entry and edit page of a branch, I want echo id, when I mouse over into edit link in edit button, its show error,: branchedit.php?id=Note:Undefined index:id in line 101, but it work properly in localhost. error picture page link : https://www.dropbox.com/s/i1vu62lz3pezia0/id%20error.JPG My code: <?php include 'include/config.php'; include 'include/opendb.php'; include 'loginheader.php'; ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Branch</title> <!--Requered Validation --> <link rel="stylesheet" type="text/css" media="screen" href="jqueryvalidation/demo/css/screen.css" /> <script src="jqueryvalidation/jquery.js" type="text/javascript"></script> <script src="jqueryvalidation/jquery.validate.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function() { $("#commentForm").validate(); }); </script> <!--End Requered Validation --> <style type="text/css"> <!-- body { background-color: #cccccc; } --> </style> <style type="text/css"> <!-- --> </style> <link href="css/usercss.css" rel="stylesheet" type="text/css" /> <style type="text/css"> <!-- .style7 { color: #000000; font-weight: bold; } .style8 {color: #FFFFFF} --> </style> </head> <body> <div id="container"> <table width="453" border="0" align="left" cellpadding="0" cellspacing="1"> <tr> <td width="451"><form name="cmxform" id="commentForm" method="post" action="insert_ac.php"> <table width="100%" border="0" cellspacing="1" cellpadding="3"> <tr> <td colspan="3" class="style2">Insert Branch into Database </td> </tr> <tr> <td width="100" height="46">Branch Code</td> <td width="18">:</td> <td width="309"><input name="branch_code" type="text" id="branch_code" minlength="3" class="required"></td> </tr> <tr> <td height="51">Branch Name</td> <td>:</td> <td><input name="branch_name" type="text" id="branch_name" class="required" ></td> </tr> <tr> <td height="47" colspan="3" align="center"> <div align="right"> <input name="Submit" type="submit" class="submit_button" value="Submit" /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div></td> </tr> </table> </form></td> </tr> </table> <!--Branch List --> <?php $sql="SELECT * FROM dc_master"; $result=mysql_query($sql); ?> <table width="436" border="1" cellpadding="2" cellspacing="0" class="table" id="list"> <tr> <td colspan="4"><div align="center" class="style7">List of Branches </div></td> </tr> <tr class="style4" > <td width="87" align="center"><span class="style8">Branch Code</span></td> <td width="176" align="center" ><span class="style8">Branch Name</span></td> <td width="70" align="center" ><span class="style8">Edit</span></td> <td width="77" align="center" ><span class="style8">Delete</span></td> </tr> <?php while($rows=mysql_fetch_array($result)){ ?> <tr> <td height="28"><div align="center" class="style3"><?php echo $rows['branch_code']; ?></div></td> <td class="style3">&nbsp;&nbsp;&nbsp;<?php echo $rows['dc_name']; ?></td> <!--link to update.php and send value of id --> <td align="center"><a href="branchedit.php?id=<?php echo $rows['id']; ?>" class="style3 style5 style5">Edit</a></td> <td align="center"><a href="delete.php?id=<?php echo $rows['id']; ?>" class="style3 style5 style5" onclick="return confirm('Are you sure, you want to delete? (After delete you can not undo or get it again) <?php ?>')">Delete</a></td> </tr> <?php } ?> </table> <span class="footer">Programmer : Prasanta Baidya / Mobile : 09830980840 / Email id : [email protected]</span></div> <?php mysql_close(); ?> </body> </html>

    Read the article

  • Form Validation using javascript in joomla...

    - by Ankur
    I want to use form validation. I have used javascript for this and I have downloaded the com_php0.1alpha-J15.tar component for writing php code but the blank entries are goes to the database. Please guide me... sample code is here... <script language="javascript" type="text/javascript"> function Validation() { if(document.getElementById("name").value=="") { document.getElementById("nameerr").innerHTML="Enter Name"; document.getElementById("name").style.backgroundColor = "yellow"; } else { document.getElementById("nameerr").innerHTML=""; document.getElementById("name").style.backgroundColor = "White"; } if(document.getElementById("email").value=="") { document.getElementById("emailerr").innerHTML="Enter Email"; document.getElementById("email").style.backgroundColor = "yellow"; } else { document.getElementById("emailerr").innerHTML=""; document.getElementById("email").style.backgroundColor = "White"; } if(document.getElementById("phone").value=="") { document.getElementById("phoneerr").innerHTML="Enter Contact No"; document.getElementById("phone").style.backgroundColor = "yellow"; } else { document.getElementById("phoneerr").innerHTML=""; document.getElementById("phone").style.backgroundColor = "White"; } if(document.getElementById("society").value=="") { document.getElementById("societyerr").innerHTML="Enter Society"; document.getElementById("society").style.backgroundColor = "yellow"; } else { document.getElementById("societyerr").innerHTML=""; document.getElementById("society").style.backgroundColor = "White"; } if(document.getElementById("occupation").value=="") { document.getElementById("occupationerr").innerHTML="Enter Occupation"; document.getElementById("occupation").style.backgroundColor = "yellow"; } else { document.getElementById("occupationerr").innerHTML=""; document.getElementById("occupation").style.backgroundColor = "White"; } if(document.getElementById("feedback").value=="") { document.getElementById("feedbackerr").innerHTML="Enter Feedback"; document.getElementById("feedback").style.backgroundColor = "yellow"; } else { document.getElementById("feedbackerr").innerHTML=""; document.getElementById("feedback").style.backgroundColor = "White"; } if(document.getElementById("name").value=="" || document.getElementById("email").value=="" || document.getElementById("phone").value=="" || document.getElementById("society").value=="" || document.getElementById("occupation").value=="" || document.getElementById("feedback").value=="") return false; else return true; } </script> <?php if(isset($_POST['submit'])) { $conn = mysql_connect('localhost','root',''); mysql_select_db('society_f',$conn); $name = $_POST['name']; $email = $_POST['email']; $phone = $_POST['phone']; $society = $_POST['society']; $occupation = $_POST['occupation']; $feedback = $_POST['feedback']; $qry = "insert into feedback values(null". ",'" . $name . "','" . $email . "','" . $phone . "','" . $society . "','" . $occupation . "','" . $feedback . "')" ; $res = mysql_query($qry); if(!$res) { echo "Could not run a query" . mysql_error(); exit(); } } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Untitled Document</title> <style type="text/css"> .td{ background-color:#FFFFFF; color:#000066; width:100px; } .text{ border:1px solid #0033FF; color:#000000; } </style> </head> <body> <form id="form1" method="post"> <input type="hidden" name="check" value="post"/> <table border="0" align="center" cellpadding="2" cellspacing="2"> <tr> <td colspan="3" style="text-align:center;"><span style="font-size:24px;color:#000066;">Feedback Form</span></td> </tr> <tr> <td class="td">Name</td> <td><input type="text" id="name" name="name" class="text" ></td> <td style="font-style:italic;color:#FF0000;" id="nameerr"></td> </tr> <tr> <td class="td">E-mail</td> <td><input type="text" id="Email" name="Email" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="emailerr"></td> </tr> <tr> <td class="td">Contact No</td> <td><input type="text" id="Phone" name="Phone" maxlength="15" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="Phoneerr"></td> </tr> <tr> <td class="td">Your Society</td> <td><input type="text" id="society" name="society" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="societyerr"></td> </tr> <tr> <td class="td">Occupation</td> <td><input type="text" id="occupation" name="occupation" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="occupationerr"></td> </tr> <tr> <td class="td">Feedback</td> <td><textarea name="feedback" id="feedback" class="text"></textarea></td> <td style="font-style:italic;color:#FF0000;" id="feedbackerr"></td> </tr> <tr> <td colspan="3" style="text-align:center;"> <input type="submit" value="Submit" id="submit" onClick="Validation();" /> <input type="reset" value="Reset" onClick="Resetme();" /> </td> </tr> </table> </form> </body> </html>

    Read the article

  • Form Validation using javascript in joomla

    - by Ankur
    I want to use form validation. I have used javascript for this and I have downloaded the com_php0.1alpha-J15.tar component for writing php code but the blank entries are goes to the database. Please guide me... sample code is here... <script language="javascript" type="text/javascript"> function Validation() { if(document.getElementById("name").value=="") { document.getElementById("nameerr").innerHTML="Enter Name"; document.getElementById("name").style.backgroundColor = "yellow"; } else { document.getElementById("nameerr").innerHTML=""; document.getElementById("name").style.backgroundColor = "White"; } if(document.getElementById("email").value=="") { document.getElementById("emailerr").innerHTML="Enter Email"; document.getElementById("email").style.backgroundColor = "yellow"; } else { document.getElementById("emailerr").innerHTML=""; document.getElementById("email").style.backgroundColor = "White"; } if(document.getElementById("phone").value=="") { document.getElementById("phoneerr").innerHTML="Enter Contact No"; document.getElementById("phone").style.backgroundColor = "yellow"; } else { document.getElementById("phoneerr").innerHTML=""; document.getElementById("phone").style.backgroundColor = "White"; } if(document.getElementById("society").value=="") { document.getElementById("societyerr").innerHTML="Enter Society"; document.getElementById("society").style.backgroundColor = "yellow"; } else { document.getElementById("societyerr").innerHTML=""; document.getElementById("society").style.backgroundColor = "White"; } if(document.getElementById("occupation").value=="") { document.getElementById("occupationerr").innerHTML="Enter Occupation"; document.getElementById("occupation").style.backgroundColor = "yellow"; } else { document.getElementById("occupationerr").innerHTML=""; document.getElementById("occupation").style.backgroundColor = "White"; } if(document.getElementById("feedback").value=="") { document.getElementById("feedbackerr").innerHTML="Enter Feedback"; document.getElementById("feedback").style.backgroundColor = "yellow"; } else { document.getElementById("feedbackerr").innerHTML=""; document.getElementById("feedback").style.backgroundColor = "White"; } if(document.getElementById("name").value=="" || document.getElementById("email").value=="" || document.getElementById("phone").value=="" || document.getElementById("society").value=="" || document.getElementById("occupation").value=="" || document.getElementById("feedback").value=="") return false; else return true; } </script> <?php if(isset($_POST['submit'])) { $conn = mysql_connect('localhost','root',''); mysql_select_db('society_f',$conn); $name = $_POST['name']; $email = $_POST['email']; $phone = $_POST['phone']; $society = $_POST['society']; $occupation = $_POST['occupation']; $feedback = $_POST['feedback']; $qry = "insert into feedback values(null". ",'" . $name . "','" . $email . "','" . $phone . "','" . $society . "','" . $occupation . "','" . $feedback . "')" ; $res = mysql_query($qry); if(!$res) { echo "Could not run a query" . mysql_error(); exit(); } } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Untitled Document</title> <style type="text/css"> .td{ background-color:#FFFFFF; color:#000066; width:100px; } .text{ border:1px solid #0033FF; color:#000000; } </style> </head> <body> <form id="form1" method="post"> <input type="hidden" name="check" value="post"/> <table border="0" align="center" cellpadding="2" cellspacing="2"> <tr> <td colspan="3" style="text-align:center;"><span style="font-size:24px;color:#000066;">Feedback Form</span></td> </tr> <tr> <td class="td">Name</td> <td><input type="text" id="name" name="name" class="text" ></td> <td style="font-style:italic;color:#FF0000;" id="nameerr"></td> </tr> <tr> <td class="td">E-mail</td> <td><input type="text" id="Email" name="Email" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="emailerr"></td> </tr> <tr> <td class="td">Contact No</td> <td><input type="text" id="Phone" name="Phone" maxlength="15" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="Phoneerr"></td> </tr> <tr> <td class="td">Your Society</td> <td><input type="text" id="society" name="society" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="societyerr"></td> </tr> <tr> <td class="td">Occupation</td> <td><input type="text" id="occupation" name="occupation" class="text"></td> <td style="font-style:italic;color:#FF0000;" id="occupationerr"></td> </tr> <tr> <td class="td">Feedback</td> <td><textarea name="feedback" id="feedback" class="text"></textarea></td> <td style="font-style:italic;color:#FF0000;" id="feedbackerr"></td> </tr> <tr> <td colspan="3" style="text-align:center;"> <input type="submit" value="Submit" id="submit" onClick="Validation();" /> <input type="reset" value="Reset" onClick="Resetme();" /> </td> </tr> </table> </form> </body> </html>

    Read the article

  • php form validation with javascript

    - by Jon Hanson
    hi guys i need help trying to figure out why the alert box doesnt show up when i run this. im also new at programming. html i due just fine. im currently taking a php class, and the teacher thought it would be fun to have us create a form and validate it. my problem is i am trying to call the function which then would validate it. My problem is its not calling it, and i cant quite figure out why. please help? jons viladating <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <link rel="stylesheet" href="decor.css" type="text/css"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>jons viladating</title> <script type="text/javascript"> <!-- <![CDATA[ function showjonsForm() { var errors = ""; // check for any empty strings if (document.forms[0].fname.value == "") errors += "fname\n"; if (document.forms[0].lname.value == "") errors += "lName\n"; if (document.forms[0].addrs1.value == "") errors += "Address\n"; if (document.forms[0].city.value == "") errors += "City\n"; if (document.forms[0].state.value == "") errors += "State\n"; if (document.forms[0].zip.value == "") errors += "Zip\n"; if (document.forms[0].phone.value == "") errors += "Phone\n"; if (document.forms[0].email.value == "") errors += "Email\n"; if (document.forms[0].pw2.value == "") errors += "Confirm password\n"; if (document.forms[0].dob.value == "") errors += "Date of birth\n"; if (document.forms[0].sex.value == "") errors += "sex\n"; // don't need to check checkboxes if (errors != "") { //something was wrong})) alert ("Please fix these errors\n" + errors) ; return false; } var stringx; stringx = "fName:" + document.forms(0).fname.value; stringx = "lName:" + document.forms(0).lname.value; stringx += "\nAddress: " + document.forms(0).addrs1.value; stringx += "\nCity: " + document.forms(0).city.value; stringx += " \nState: " + document.forms(0).state.value; stringx += " Zip: "+ document.forms(0).zip.value; stringx += "\nPhone: " + document.forms(0).phone.value; stringx += "\nE-mail:" + document.forms(0).email.value; stringx += "\nConfirm password " + document.forms(0).pw2.value; stringx += "\nDate of birth: " + document.forms(0).dob.value; stringx += "\nSex: " + document.forms(0).sex.value; alert(stringx); return false //set to false to not submit } // ]]> --> </script> <h1>jons validations test</h1> </head> <body> <div id="rightcolumn"> <img src="hula.gif" align="right"/> </div> <text align="left"> <form name="jon" action="formoutput.php" onsubmit="return showjonsForm()" Method="post"> <fieldset style="width:250px"> <label> first name</label> <input type="text" name="fname" size="15" maxlength="22" onBlur="checkRequired( this,'fname')"/><br /> <label>last name</label> <input type="text" name="lname" size="10" maxlength="22"> <br /> </fieldset> <fieldset style="width:250px"> <label>address</label> <input type="text" name="adrs1" size="10" maxlength="30"><br /> <span class="msg_container" id="adrs2"></span><br /> <label>city</label> <input type="text" name="city" size="10" maxlength="15"><br /> <span class="msg_container" id="city"></span><br /> <label>state</label> <input type="text" name="state" size="10" maxlength="2"><br /> <span class="msg_container" id="state"></span><br /> <label>zip</label> <input type="text" name="zip" size="10" maxlength="5"><br /> </fieldset> <fieldset style="width:250px"> <label>phone</label> <input type="text" name="phone" size="10" maxlength="10"><br /> <div>please input phone number in this format 1234567892 thank you </div> <label>email</label> <input type="text" name="email" size="10" maxlength="22"><br /> <div> password must have 1 number upper case and minimum of 6 charcters</div> <label>password</label> <input type="text" name="pw2" size="10" maxlength="12"><br /> <label>select gender type</label> <select name="sex" size="1" <br /> <option>male</option> <option>female</option> <option>timelord</option> </select> <label>date of birth</label> <input type="text name="dob" size="8" maxlength="8"/> <div> would you like to know know more</div> <label> yes</label> <input type="checkbox" checked="checked" name="check" /> </fieldset> <input type="submit"/></form> </form> <div id="footer"> <img src="laps2.jpg"> <img src="orange.jpg"><img src="ok.jpg"> </div> </body> </html>

    Read the article

  • Problems using Hibernate and Spring in web application

    - by user628480
    Hi.I'm having NullPointerException trying to getCurrentSession() java.lang.NullPointerException servlets.ControlServlet.doPost(ControlServlet.java:46) javax.servlet.http.HttpServlet.service(HttpServlet.java:709) javax.servlet.http.HttpServlet.service(HttpServlet.java:802) I use Tomcat 5.5 index.jsp page: <%@ page language="java" contentType="text/html; charset=ISO-8859-1"pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title></title> </head> <body> <%@ page import="java.util.List" %> <%@ page import="data.Singer" %> <jsp:useBean id="singer" class="data.Singer" scope="session"/> <jsp:setProperty name="singer" property="*" /> <form action="ControlServlet" method="POST"> <form method=“POST”> Name:<br /> <input type=“text” name="name" /><br /> Type:<br /> <input type=“text” name="type" /><br /> <input type="submit" name="Add song" value="Add song"> <input type="submit" name="save" value="Save" /><br><br> <input type ="submit" name="values" value="Get values" > </form> </body> </html> web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" 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"> <display-name>webproject</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/beans.xml, /WEB-INF/conf.xml, /WEB-INF/singers.hbm.xml, /WEB-INF/songs.hbm.xml, /WEB-INF/singerbeans.xml, /WEB-INF/songbeans.xml</param-value> </context-param> <servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>test</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>*.*</url-pattern> </servlet-mapping> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/beans.xml, /WEB-INF/conf.xml, /WEB-INF/singers.hbm.xml, /WEB-INF/songs.hbm.xml, /WEB-INF/singerbeans.xml, /WEB-INF/songbeans.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet> <description> </description> <display-name>ControlServlet</display-name> <servlet-name>ControlServlet</servlet-name> <servlet-class>servlets.ControlServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ControlServlet</servlet-name> <url-pattern>/ControlServlet</url-pattern> </servlet-mapping> </web-app> ControlServlet.java public class ControlServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Autowired private SingerDao singerdao; public SingerDao getSingerDao() { return singerdao; } public void setSingerDao(SingerDao singerdao) { this.singerdao = singerdao; } public ControlServlet() { super(); // TODO Auto-generated constructor stub } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (request.getParameter("values") != null) { response.getWriter().println(singerdao.getDBValues()); } } } and SingerDao.java public class SingerDao implements SingerDaoInterface { @Autowired private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public List getDBValues() { Session session = getCurrentSession(); List<Singer> singers = session.createCriteria(Singer.class).list(); return singers; } private org.hibernate.classic.Session getCurrentSession() { return sessionFactory.getCurrentSession(); } public void updateSinger(Singer singer) { Session session = getCurrentSession(); session.update(singer); } public Singer getSinger(int id) { Singer singer = null; Session session = getCurrentSession(); singer = (Singer) session.load(Singer.class, id); return singer; } public void deleteSinger(Singer singer) { Session session = getCurrentSession(); session.delete(singer); } public void insertRow(Singer singer) { Session session = getCurrentSession(); session.save(singer); } } In simple Java Project it works fine.I think sessionFactory doesn't autowires,but why? Thanks all.

    Read the article

  • jstl code issue

    - by theJava
    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <style type="text/css"> .even { background-color: silver; } </style> <title>Registration Page</title> </head> <body> <form:form action="add.htm" commandName="user"> <table> <tr> <td>User Name :</td> <td><form:input path="name" /></td> </tr> <tr> <td>Password :</td> <td><form:password path="password" /></td> </tr> <tr> <td>Gender :</td> <td><form:radiobutton path="gender" value="M" label="M" /> <form:radiobutton path="gender" value="F" label="F" /></td> </tr> <tr> <td>Country :</td> <td><form:select path="country"> <form:option value="0" label="Select" /> <form:option value="India" label="India" /> <form:option value="USA" label="USA" /> <form:option value="UK" label="UK" /> </form:select></td> </tr> <tr> <td>About you :</td> <td><form:textarea path="aboutYou" /></td> </tr> <tr> <td>Community :</td> <td><form:checkbox path="community" value="Spring" label="Spring" /> <form:checkbox path="community" value="Hibernate" label="Hibernate" /> <form:checkbox path="community" value="Struts" label="Struts" /></td> </tr> <tr> <td></td> <td><form:checkbox path="mailingList" label="Would you like to join our mailinglist?" /></td> </tr> <tr> <td colspan="2"><input type="submit" value="Register"></td> </tr> </table> </form:form> <c:if test="${fn:length(userList) > 0}"> <table cellpadding="5"> <tr class="even"> <th>Name</th> <th>Gender</th> <th>Country</th> <th>About You</th> </tr> <c:forEach items="${userList}" var="user" varStatus="status"> <tr class="<c:if test="${status.count % 2 == 0}">even</c:if>"> <td>${user.name}</td> <td>${user.gender}</td> <td>${user.country}</td> <td>${user.aboutYou}</td> </tr> </c:forEach> </table> </c:if> </body> </html> When i execute my jsp page, this piece of code does not show up at all. The full source code is below. <c:if test="${fn:length(userList) > 0}"> <table cellpadding="5"> <tr class="even"> <th>Name</th> <th>Gender</th> <th>Country</th> <th>About You</th> </tr> <c:forEach items="${userList}" var="user" varStatus="status"> <tr class="<c:if test="${status.count % 2 == 0}">even</c:if>"> <td>${user.name}</td> <td>${user.gender}</td> <td>${user.country}</td> <td>${user.aboutYou}</td> </tr> </c:forEach> </table> </c:if>

    Read the article

  • Using Flot's Bar Graph in an Android WebView with Highlighting

    - by Nicholi
    The issue is unhighlighting bars which are no longer selected in a bar graph plotted by flot in a WebView on Android. Got no other issues drawing the actual graphs (which look beautiful for something so simple btw). I am not extremely knowledgeable in terms of javascript and web design/development but it seems little should have been needed, if it would just work!! :( I believe I'm following the Flot API correctly, if not someone please scream and yell at me. It seems to work just fine in a non-mobile browser at least. Hoping someone has done this before, but if not I've got the minimal necessary code to poke at your droids if inquiring minds would like to test. I've tested on two Nexus Ones (both 2.2.1), and have tried targeting with Andriod 1.5 and 2.2 SDKs (my intention is to target 1.5 if possible). I've been attempting to hack away at this for far too long on my own now. What happens: 1. Graph loads fine with bars. All bars unhighlighted. 2. Select a bar in graph, gets highlighted fine (and a tooltip is placed). 3. Select a different bar in graph, old bar is unhighlighted, old tooltip removed, new bar highlighted and tooltip placed (still no problems). 4. Click in the vast darkness of the graph which should then unhighlight the last bar... but it doesn't. I've tried disabling flot's autohighlight and manually doing it as well to no avail. Looking into flot itself and only getting down to drawOverlay() where the issue seems to begin... An even more disturbing bug(?) appears if the fill bar option is enabled in the graph, but I'd rather just forget about that for now. Also grabbed the latest version of flot from their svn (r290), but made no different from last public release (v0.6). As a complete guess I'm thinking it's an issue with WebKit's javascript implementation (or something specific to Nexus Ones, which wouldn't be so bad), but if there is any ugly hack to just get it to work I'm all ears. I've thrown the graph data directly into the html/js, rather than deal with showing all the code involved in the Java-javascript handler and callbacks. The simple html placed in 'assets/flot/test/' with jquery.js and jquery.flot.js: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="jquery.js"></script> <script src="jquery.flot.js"></script> <script id="source" language="javascript" type="text/javascript"> var lastItem = null; var plot = null; $(document).ready(function () { //window.testhandler.loadGraph(); // bind plotclick here $("#graphHolder").bind("plotclick", function (event, pos, item) { if (item) { var lastPoint = null; if (lastItem != null) lastPoint = lastItem.datapoint; if (!pointEquals(lastPoint, item.datapoint)) { //if (lastItem != null) // plot.unhighlight(lastItem.series, lastItem.datapoint); lastItem = item; $("#tooltip").remove(); //plot.highlight(item.series, item.datapoint); showTooltip(item.pageX, item.pageY, item.datapoint[1]); } } else if (lastItem != null) { plot.unhighlight(lastItem.series, lastItem.datapoint); // not unhighlighting anything //plot.unhighlight(); // doesn't work either, supposed to unhighlight everything lastItem = null; $("#tooltip").remove(); } }); GotGraph(); }); /** * Show a tooltip above bar in graph * @param {int} x Left coordinate of div * @param {int} y Top coordinate of div * @param {String} contents text to place in div */ function showTooltip(x, y, contents) { $('<div id="tooltip">' + contents + '</div>').css( { position: 'absolute', display: 'none', top: y, left: x, border: '1px solid #fdd', padding: '2px', 'background-color': '#fee', opacity: 0.80 }).appendTo("body").fadeIn(200); } /** * Draw the graph. This is a callback which will be called by Java * * @param {Object} seriesData * @param {Object} seriesOptions */ function GotGraph() { //seriesData, seriesOptions) { var seriesData = [{ "bars":{"lineWidth":2,"show":true,"barWidth":86400000,"align":"center","fill":false}, "data":[[1288569600000,10],[1288656000000,5],[1288742400000,12],[1288828800000,20],[1288915200000,14],[1289001600000,3],[1289174400000,22],[1289260800000,20],[1289347200000,10],[1289433600000,5],[1289520000000,12],[1289606400000,20],[1289692800000,14],[1289779200000,35]]}]; var seriesOptions = { "xaxis":{"twelveHourClock":false,"minTickSize":[1,"day"],"tickSize":[1,"day"],"timeformat":"%d","mode":"time"}, "yaxis":{"min":0}, "grid":{"clickable":true,"autoHighlight":true,"hoverable":false}}; plot = $.plot($("#graphHolder"), seriesData, seriesOptions); } function pointEquals(point1, point2) { if (point1 != null && point2 != null && typeof(point1) == typeof(point2) && point1.length == point2.length) { var i; for (i=0;i<point1.length;i++) { if (point1[i] != point2[i]) { return false; } } return true; } return false; } </script> </head> <body> <div id="graphHolder" STYLE="height:200px;width:400px"></div> </body> </html> The minimal amount of code necessary in onCreate in startup activity: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView mytestView = new WebView(this); mytestView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); setContentView(mytestView); mytestView.setBackgroundColor(0); mytestView.getSettings().setJavaScriptEnabled(true); mytestView.setClickable(true); mytestView.setFocusable(false); mytestView.setFocusableInTouchMode(false); mytestView.loadUrl("file:///android_asset/flot/test/stats_graph.html"); }

    Read the article

  • Submit a form by code

    - by user1440235
    I am trying to programmatically submit a form but get an error that says: SCRIPT5007: Unable to get value of the property 'submit': object is null or undefined verify1.php, line 9 character 5 Can anyone see what I am doing wrong? Here is the code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Untitled Document</title> <script type="text/javascript"> function submitform() { document.getElementById("repeatForm").submit(); } </script> </head> <body> <?php require_once('recaptchalib.php'); $privatekey = "6Ld1N9ISAAAAAB_lXt0Es0muh2cfikSgVrUP4ZXh"; $resp = recaptcha_check_answer ($privatekey, $_SERVER["REMOTE_ADDR"], $_POST["recaptcha_challenge_field"], $_POST["recaptcha_response_field"]); if (!$resp->is_valid) { // What happens when the CAPTCHA was entered incorrectly echo '<script language="JavaScript">submitform();</script>'; ; /*echo "<script>window.location.href = 'Information-Request-Voodoo-Websites.php';</script>";*/ } else { echo "<script>window.location.href = 'Confirm-Information-Request.html';</script>"; // Your code here to handle a successful verification } ?> <?php if (isset($_POST['name2'])) $_SESSION['name2'] =$_POST['name2']; if (isset($_POST['phone'])) $_SESSION['phone'] =$_POST['phone']; if (isset($_POST['email'])) $_SESSION['email'] =$_POST['email']; if (isset($_POST['company'])) $_SESSION['company'] =$_POST['company']; if (isset($_POST['pages'])) $_SESSION['pages'] =$_POST['pages']; if (isset($_POST['shopping'])) $_SESSION['shopping'] =$_POST['shopping']; if (isset($_POST['new'])) $_SESSION['new'] =$_POST['new']; if (isset($_POST['general'])) $_SESSION['general'] =$_POST['general']; if (isset($_POST['respond'])) $_SESSION['respond'] =$_POST['respond']; ?> <form id="repeatForm" action="Information-Request-Voodoo-Websites.php" method="post"> <span name="sprytextfield1"> <label for="name2">Please enter your name:</label> <input name="name" type="text" class="inputTextBoxFormat" id="name2" value="<?php echo((isset($_POST["name"]))?$_POST["name"]:"") ?>" size="30" /> <span class="textfieldRequiredMsg">A value is required.</span></span> <p><span id="sprytextfield2"> <label for="phone">Please enter your phone number:</label> <input name="phone" type="text" class="inputTextBoxFormat" id="phone" value="<?php echo((isset($_POST["phone"]))?$_POST["phone"]:"") ?>" /> <span class="textfieldRequiredMsg">A value is required.</span></span></p> <p><span id="sprytextfield3"> <label for="email">Please enter your email address:</label> <input name="email" type="text" class="inputTextBoxFormat" id="email" value="<?php echo((isset($_POST["email"]))?$_POST["email"]:"") ?>" size="40" /> <span class="textfieldRequiredMsg">A value is required.</span><span class="textfieldInvalidFormatMsg">Invalid format.</span></span></p> <p><span id="sprytextarea1"> <label for="company">Enter a brief description of your company:</label> <br /> <textarea name="company" cols="65" rows="3" class="inputTextBoxFormat" id="company"><?php echo((isset($_POST["company"]))?$_POST["company"]:"") ?></textarea> <span class="textareaRequiredMsg">A value is required.</span></span></p> <p>Anticipated number of pages:<span id="sprytextfield4"> <label for="pages"></label> <input name="pages" type="text" class="inputTextBoxFormat" id="pages" value="<?php echo((isset($_POST["pages"]))?$_POST["pages"]:"") ?>" size="7" /> <span class="textfieldRequiredMsg">A value is required.</span></span><span id="spryselect1"> <label for="shopping">Shopping cart required?</label> <select name="shopping" class="inputTextBoxFormat" id="shopping"> <option value="yes">yes</option> <option value="no">no</option> </select> <span class="selectRequiredMsg">Please select an item.</span></span></p> <p><span id="spryselect2"> <label for="new">Does this work concern a new or existing web site?</label> <select name="new" class="inputTextBoxFormat" id="new"> <option value="existing" <?php if (!(strcmp("existing", ((isset($_POST["new"]))?$_POST["new"]:"")))) {echo "selected=\"selected\"";} ?>>existing</option> <option value="new" <?php if (!(strcmp("new", ((isset($_POST["new"]))?$_POST["new"]:"")))) {echo "selected=\"selected\"";} ?>>new</option> </select> <span class="selectRequiredMsg">Please select an item.</span></span></p> <p><span id="sprytextarea2"> <label for="general">Add any additiional comments here or ask questions. </label> <textarea name="general" cols="65" rows="4" class="inputTextBoxFormat" id="general"><?php echo((isset($_POST["general"]))?$_POST["general"]:"") ?></textarea> </span></p> <p><span id="spryselect3"> <label for="respond">How would you like us to respond?</label> <select name="respond" class="inputTextBoxFormat" id="respond"> <option value="email" <?php if (!(strcmp("email", ((isset($_POST["respond"]))?$_POST["respond"]:"")))) {echo "selected=\"selected\"";} ?>>email</option> <option value="phone" <?php if (!(strcmp("phone", ((isset($_POST["respond"]))?$_POST["respond"]:"")))) {echo "selected=\"selected\"";} ?>>phone</option> </select> <input type="submit" name="formSubmit" value="Submit" /> </form> </body> </html>

    Read the article

  • Integrating PayMill: The token filled input field is not created, error "field_invalid_amount"

    - by automatix
    I'm implementing the Credit Card Payment form of PayMill according to the Payment Form docu. So I copied the JS from the Bridge docu page and the form from the Payment Form docu page. But no token is created. When I try to debug the JS and add console.info(error.apierror); into the paymillResponseHandler(...) function, I get the error code: field_invalid_amount. According to the support page There are three possible reasons for this error message: no amount value was provided numbers were rounded wrong delimiter symbol But the amuont is provided and I've already tried different delimiter symbols. What "numbers were rounded" means, is not clear. What can be the problem and how to fix this issue? Code: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta name="generator" content="PSPad editor, www.pspad.com"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <title> </title> </head> <body> <!-- PayMill HEAD start --> <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/css/bootstrap.no-responsive.no-icons.min.css" /> <script type="text/javascript"> var PAYMILL_PUBLIC_KEY = '51668632777bf03b57f861c5a7278a38'; </script> <script type="text/javascript" src="https://bridge.paymill.com/"></script> <!-- PayMill HEAD stop --> <!-- PayMill FORM start --> <form id="payment-form" class="span4" action="payment.php" method="POST"> <p class="payment-errors alert-error span3" style="display:none;"> </p> <div id="payment-form-cc"> <div class="controls controls-row"> <div class="span2"> <label class="card-number-label">Kreditkarte </label> <input class="card-number span2" type="text" size="20" value="4111111111111111"/> </div> <div class="span1"> <label class="card-cvc-label">CVC </label> <input class="card-cvc span1" type="text" size="4" value="111"/> </div> </div> <div class="controls controls-row"> <div class="span3 card-icon"> </div> </div> <div class="controls controls-row"> <div class="span3"> <label class="card-holdername-label">Karteninhaber </label> <input class="card-holdername span3" type="text" size="20" value="lala"/> </div> </div> <div class="controls controls-row"> <div class="span3"> <label class="card-expiry-label">Gültigkeitsdatum (MM/YYYY) </label> <input class="card-expiry-month span1" type="text" size="2" value="12"/> <span style="float:left;"> / </span> <input class="card-expiry-year span1" type="text" size="4" value="2015"/> </div> </div> </div> <div class="controls controls-row"> <div class="span2"> <label class="amount-label">Betrag </label> <input class="amount span2" type="text" size="5" value="9,99" name="amount"/> </div> <div class="span1"> <label class="currency-label">Währung </label> <input class="currency span1" type="text" size="3" value="EUR" name="currency"/> </div> </div> <div class="controls controls-row"> <div class="span4"> <button class="submit-button btn btn-primary" type="submit" >Pay!</button> </div> </div> </form> <!-- PayMill FORM stop --> <!-- PayMill FOOT start --> <script type="text/javascript"> function paymillResponseHandler(error, result) { if (error) { console.info(error.apierror); // Displays the error above the form $(".payment-errors").text(error.apierror); } else { console.info('OK'); var form = $("#payment-form"); // Output token var token = result.token; // Insert token into form in order to submit to server form.append( "<input type='hidden' name='paymillToken' value='"+token+"'/>" ); // Submit form form.get(0).submit(); } } </script> <script type="text/javascript"> paymill.createToken({ number: $('.card-number').val(), // required exp_month: $('.card-expiry-month').val(), // required exp_year: $('.card-expiry-year').val(), // required cvc: $('.card-cvc').val(), // required amount_int: $('.card-amount-int').val(), // required, e.g. "4900" for 49.00 EUR currency: $('.currency').val(), // required cardholder: $('.card-holdername').val() // optional }, paymillResponseHandler); </script> <!-- PayMill FOOT stop --> </body> </html>

    Read the article

  • Create an axpanding image with CSS and div or span

    - by user1594895
    I have a complex image cutted up in alot of slice. You can see http://jsfiddle.net/yefQR/ <!--Force IE6 into quirks mode with this comment tag--> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Page Title</title> <style type="text/css"> body{ margin: 0; padding: 0; border: 0; overflow: hidden; height: 100%; max-height: 100%; } #framecontentTop, #framecontentBottom{ position: absolute; top: 0; left: 0; width: 100%; height: 130px; /*Height of top frame div*/ overflow: hidden; /*Disable scrollbars. Set to "scroll" to enable*/ background-color: navy; color: white; } #framecontentBottom{ top: auto; bottom: 0; height: 110px; /*Height of bottom frame div*/ overflow: hidden; /*Disable scrollbars. Set to "scroll" to enable*/ background-color: navy; color: white; } #maincontent{ position: fixed; top: 130px; /*Set top value to HeightOfTopFrameDiv*/ left: 0; right: 0; bottom: 110px; /*Set bottom value to HeightOfBottomFrameDiv*/ overflow: auto; background: #fff; } .innertube{ margin: 15px; /*Margins for inner DIV inside each DIV (to provide padding)*/ } * html body{ /*IE6 hack*/ padding: 130px 0 110px 0; /*Set value to (HeightOfTopFrameDiv 0 HeightOfBottomFrameDiv 0)*/ } * html #maincontent{ /*IE6 hack*/ height: 100%; width: 100%; } </style> </head> <body> <div id="framecontentTop"> <div class="innertube"> <div id="screenshot%20tsam%20900r2c2" style=" background-color: green;position:absolute; left:4px; top:6px; width:20px; height:68px; z-index:1; visibility:visible; "> </div> <div id="screenshot%20tsam%20900r2c3" style="background-color: yellow; position:absolute; left:24px; top:6px;width:47px; height:68px;z-index:2; visibility:visible;"></div> <div id="screenshot%20tsam%20900r2c4" style="background-color: red; position:absolute; left:71px; top:6px;width:165px; height:68px;z-index:3; visibility:visible;"></div> <div id="screenshot%20tsam%20900r2c5" style="background-color: black; position:absolute; left:236px; top:6px;width:62px; height:68px;z-index:4; visibility:visible;"></div> <div id="screenshot%20tsam%20900r2c6" style="background-color: pink; position:absolute; left:298px; top:6px;width:147px; height:68px;z-index:5; visibility:visible;"></div> <div id="screenshot%20tsam%20900r2c7" style="background-color: orange; position:absolute; left:445px; top:6px;width:311px; height:37px;z-index:6; visibility:visible;"></div> <div id="screenshot%20tsam%20900r2c9" style="background-color: cyan; position:absolute; left:756px; top:6px;width:108px; height:37px;z-index:7; visibility:visible;"></div> <div id="screenshot%20tsam%20900r2c11" style="background-color: white; position:absolute; left:864px; top:6px;width:27px; height:37px;z-index:8; visibility:visible;"></div> <div id="screenshot%20tsam%20900r3c7" style="background-color: DodgerBlue; position:absolute; left:445px; top:43px;width:8px; height:31px;z-index:9; visibility:visible;"></div> <div id="screenshot%20tsam%20900r3c8" style="background-color: Gold; position:absolute; left:453px; top:43px;width:355px; height:31px;z-index:10; visibility:visible;"></div> <div id="screenshot%20tsam%20900r3c10" style="background-color: LightCyan ; position:absolute; left:808px; top:43px;width:83px; height:31px;z-index:11; visibility:visible;"></div> </div> </div> <div id="framecontentBottom"> <div class="innertube"> <h3>Sample text here</h3> </div> </div> <div id="maincontent"> <div class="innertube"> <h1>Lorem</h1> <p> Lorem ipsum </p> <p style="text-align: center">Vestibulum </p> </div> </div> </body> </html> Id like to make : 1) the header image autoexpanding using the repeated-y css property of DodgerBlue color and Orange div because thy are the only 2 part of image axpandible. 2) Is it possible to define a minimum size of header, and is possible to make the entire body minimum size based that size so the browser cant get smaller an if the window get smaller, scrollbar is show.

    Read the article

  • Stretch UL to fill the entire DIV

    - by Interfaith
    There is a similar post: Stretch horizontal ul to fit width of div But mine is a little bit tricky, as I have tried the above example but failed. My code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-… <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title></title> <script type='text/javascript' src='https://ajax.googleapis.com/ajax/li… <script> function mainmenu(){ $(" #nav ul ").css({display: "none"}); // Opera Fix $(" #nav li").hover(function(){ $(this).find('ul:first').css({visibi… "visible",display: "none"}).show(400); },function(){ $(this).find('ul:first').css({visibi… "hidden"}); }); } $(document).ready(function(){ mainmenu(); }); </script> <style> body{ font-size:0.85em; font-family:Verdana, Arial, Helvetica, sans-serif; } #nav, #nav ul{ margin:0; padding:0; list-style-type:none; list-style-position:outside; position:relative; line-height:1.5em; display: table; width: 100%; } #nav a{ display:block; padding:10px 15px 10px 15px; border:1px solid #fff; color:#fff; text-align: center; margin:0; text-decoration:none; background: #C34328; border-top:1px solid #EF593B; -moz-box-shadow:0px 3px 4px #591E12 inset; -webkit-box-shadow:0px 3px 4px #591E12 inset; -box-shadow:0px 3px 4px #591E12 inset; } #nav a:hover{ background-color:#fff; color:#333; } #nav li{ float:left; position:relative; } #nav ul { position:absolute; display:none; width:12em; top:3.2em; } #nav li ul a{ width:12em; height:auto; float:left; } #nav ul ul{ top:auto; } #nav li ul ul { left:12em; margin:0px 0 0 10px; } </style> </head> <body> <div style="width: 980px; border: 1px black solid;"> <ul id="nav"> <li><a href="#">Find a Doctor</a></li> <li><a href="#">Why Interfaith</a></li> <li><a href="#">For Patients & Visitors</a> <ul> <li><a href="#">3.1 jQuery</a></li> <li><a href="#">3.2 Mootools</a></li> <li><a href="#">3.3 Prototype</a></li> </ul> </li> <li><a href="#">Medical Services</a> <ul> <li><a href="#">Behavioral Health</a></li> <li><a href="#">Clinical Laboratory</a></li> <li><a href="#">Dentistry</a></li> <li><a href="#">Emergency</a></li> <li><a href="#">Gynecology</a></li> <li><a href="#">Medicine</a></li> <li><a href="#">Pastoral</a></li> <li><a href="#">Pediatrics</a></li> <li><a href="#">Physical Medicine & Rehab</a></li> </ul> </li> <li><a href="#">Medical Trainings</a> <ul> <li><a href="#">Medical Training</a></li> <li><a href="#">Behavioral Health</a></li> <li><a href="#">Predoctoral Externship</a></li> <li><a href="#">Podiatric Residency</a></li> <li><a href="#">Dental Residency</a></li> <li><a href="#">Pulmonary Medicine</a></li> </ul> </li> <li><a href="#">Contact</a></li> </ul> </div> </body> </html> Can someone tell me where I have to edit to complete the code? Thanks

    Read the article

  • PHP Using session variables in array(s)

    - by Chris
    Hello, My question is how do i put these session variables into a array? I have tried countless ways but none of them work. Not really sure what to put in a array and what no and how to adress them. Currently when i fill in the form the data gets displayed in a table. Next when i press the hyperlink that takes me back to the same form, i wish to enter data again. This data should be added in a new row in the same display table. Best Regards. The code below (pardon me that it is not english). <?php session_start(); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-Strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>ExpoFormulier</title> <body> <?php if (!empty($_POST)) { $standnaam = $_POST["standnaam"]; $oppervlakte = $_POST["oppervlakte"]; //value in the form van checkboxes op 1 zetten! $verdieping = isset($_POST["verdieping"]) ? $_POST["verdieping"] : 0; $telefoon = isset($_POST["telefoon"]) ? $_POST["telefoon"] : 0; $netwerk = isset($_POST["netwerk"]) ? $_POST["netwerk"] : 0; if (is_numeric($oppervlakte)) { $_SESSION["standnaam"]=$standnaam; $_SESSION["oppervlakte"]=$oppervlakte; $_SESSION["verdieping"]=$verdieping; $_SESSION["telefoon"]=$telefoon; $_SESSION["netwerk"]=$netwerk; header("Location:ExpoOverzicht.php"); } else { echo "<h1>Foute gegevens, Opnieuw invullen a.u.b</h1>"; } } ?> <form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post" id="form1"> <h1>Vul de gegevens in</h1> <table> <tr> <td>Standnaam:</td> <td><input type="text" name="standnaam" size="18"/></td> </tr> <tr> <td>Oppervlakte (in m^2):</td> <td><input type="text" name="oppervlakte" size="6"/></td> </tr> <tr> <td>Verdieping:</td> <td><input type="checkbox" name="verdieping" value="1"/></td> </tr> <tr> <td>Telefoon:</td> <td><input type="checkbox" name="telefoon" value="1"/></td> </tr> <tr> <td>Netwerk:</td> <td><input type="checkbox" name="netwerk" value="1"/></td> </tr> <tr> <td><input type="submit" name="verzenden" value="Verzenden"/></td> </tr> </table> </form> Second File: <?php session_start(); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-Strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>ExpoOverzicht</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <link href="StyleSheetExpo.css" rel="stylesheet" type="text/css" /> </head> <body> <h1>Overzicht van de ingegeven standen in deze sessie</h1> <?php $standnaam = $_SESSION["standnaam"]; $oppervlakte = $_SESSION["oppervlakte"]; $verdieping = $_SESSION["verdieping"]; $telefoon = $_SESSION["telefoon"]; $netwerk = $_SESSION["netwerk"]; $result1 = 0; $result2 = 0; $result3 = 0; $prijsCom = 0; $prijsVerdieping = 0; for ($i=1; $i <= $oppervlakte; $i++) { if($i <= 10) { $tarief1 = 1 * 100; $result1 += $tarief1; } if($i > 10 && $i <= 30) { $tarief2 = 1 * 90; $result2 += $tarief2; } if($i > 30) { $tarief3 = 1 * 80; $result3 += $tarief3; } } $prijsOpp = $result1 + $result2 + $result3; if($verdieping == 1) { $prijsVerdieping = $oppervlakte * 120; } if(($telefoon == 1) || ($netwerk == 1)) { $prijsCom = 20; } if(($telefoon == 1) && ($netwerk == 1)) { $prijsCom = 30; } $totalePrijs = $prijsOpp + $prijsVerdieping + $prijsCom; echo "<table class=\"tableExpo\">"; echo "<th>Standnaam</th>"; echo "<th>Oppervlakte</th>"; echo "<th>Verdieping</th>"; echo "<th>Telefoon</th>"; echo "<th>Netwerk</th>"; echo "<th>Totale prijs</th>"; echo "<tr>"; echo "<td>".$standnaam."</td>"; echo "<td>".$oppervlakte."</td>"; echo "<td>".$verdieping."</td>"; echo "<td>".$telefoon."</td>"; echo "<td>".$netwerk."</td>"; echo "<td>".$totalePrijs."</td>"; echo "</tr>"; echo "</table>"; ?> <a href="ExpoFormulier.php">Terug naar het formulier</a> </body> </html> </body> </html>

    Read the article

  • HTML/CSS formating

    - by Codeguy007
    I'm having to issues lining up items properly in my html code. I am not sure why they are lining up the way I want them to. First the header My Color Library is a full line height above the horizontal ruler. I want it right above the ruler. Second my X box in the td with the background is justified right fine but I actually want it in the top right hand corner not centered vertically. Here's some example html: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>FunctionalColor&amp;Design</title> </head> <html> <body> <table style="width=900px; margin-left: auto; margin-right: auto;"> <tr> <td> <P> <div style="font-size: 1em; line-height: 1em; font-weight: bolder; padding: 0px;">My Color Library</div> <div align="right" class="removeall"> <a href="colors"> <img src="http://2100computerlane.net/workingproject/images/x-button.png" /> <bold>Remove All</bold> </a> </div> <HR/></p> <div class="mycolor"> <table><!--width="900px" --> <tr> <td style="border: none; background-color: #f8d3cf; width:125px; height:80px; border-spacing: 10px; padding:0;"> <div style="padding:0; vertical-align:top;" align="right" class="remove"> <a href="f8d3cf" style="padding: 0px;"> <img src="http://2100computerlane.net/workingproject/images/x-button.png" style="padding: 0px;"/> </a> </div> </td> <td style="border: none; width:10px;"></td> <td style="border: none; background-color: #f8d3cf; width:125px; height:80px; border-spacing: 10px; padding:0;"></td> <td style="border: none; width:10px;"></td> <td style="border: none; background-color: #f8d3cf; width:125px; height:80px; border-spacing: 10px; padding:0;"></td> <td style="border: none; width:10px;"></td> <td style="border: none; background-color: #f8d3cf; width:125px; height:80px; border-spacing: 10px; padding:0;"></td> <td style="border: none; width:10px;"></td> <td style="border: none; background-color: #f8d3cf; width:125px; height:80px; border-spacing: 10px; padding:0;"></td> <td style="border: none; width:10px;"></td> <td style="border: none; background-color: #f8d3cf; width:125px; height:80px; border-spacing: 10px; padding:0;"></td> <tr> <td style="border: none; font:.6em Arial, Helvetica, sans-serif; width:125px; height:20px;">Desert Warmth<br/>70YR 56/190 A0542</td> </tr> </table> </div> </td> </tr> </table> </body> </html>

    Read the article

  • Using tinybutstrong templating system, how do I have a (secondary) mysql query (sub-block), inside a

    - by desbest
    This is the code that works well. $TBS->MergeBlock("items",$conn,"SELECT * FROM items WHERE categoryid = $getcategory"); and it has a good job of looping the items with no problem. <tr id="itemid_[items.id;block=tr]"> <td height="30"> <!-- <img src="move.png" align="left" style="margin-right: 8px;"> --> <div class="lowlight">[items.title] </div> </td> <td height="30"> <div class="editable" itemid="$item[id]">[items.quantity]</div> </td> <td height="30"> <!-- <img src="pencil.png" id="edititem"width="24" height="24"> --> &nbsp; &nbsp; &nbsp; &nbsp;<img src="icons/folder.png" id="category_[items.categoryid]";" class="changecategory" categoryid="[items.categoryid]" itemid="[items.id]" itemtitle="[items.title]" title="Change category" width="24" height="24"> &nbsp; &nbsp; &nbsp; &nbsp; <a href="index.php?category=[var.getcategory]&deleteitem=[items.id]" title="Delete item" onclick="return confirm('Are you sure you want to delete [items.title]?')"><img src="icons/trash.png" id="deleteitem" width="24" height="24"></a> </td> </tr> This is where the problem lies. In the table row I would like a secondary mysql merge block based on the id column that the primary (items) mysql table has. This means that ideally I would love to do this. $TBS->MergeBlock("fields",$conn,"SELECT * FROM items WHERE categoryid = [items.id]"); So then when I used [fields.value;block=div] inside the table row, it would pick up the a row from the fields table based on the primary mysql query. It would recognise what the id is for the merged block and perform a mysql query based on a variable that that block has. So that's what I would like to do and that's what I call a secondary mysql merge block. This is what I attempted by using the sub-blocks example and modifying it. index.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>TinyButStrong - Examples - subblocks</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <link href="tbs_us_examples_0styles.css" rel="stylesheet" type="text/css"> <style type="text/css"> <!-- .border02 { border: 2px solid #39C; } .border03 { border: 2px solid #396; } --> </style> </head> <body> <table width="400" align="center" cellpadding="5" cellspacing="0" style="border-collapse:collapse;"> <tr> <td class="border02"><strong>Item name:</strong> [item.title;block=tr] , <strong>Item quantity:</strong> [item.quantity]<br> <table border="1" align="center" cellpadding="2" cellspacing="0"> <tr bgcolor="#CACACA"> <td width="30"><u>Position</u></td> <td width="150"><u>Attribute</u></td> <td width="50"><u>Value</u></td> <td width="100"><div align="center"><u>Date Number</u></div></td> </tr> <tr bgcolor="#F0F0F0"> <td>[field.#]</td> <td>[field.attribute;block=tr;p1=[item.id]] <br><b>[item.id]</b> </td> <td><div align="right">[field.value]</div></td> <td><div align="center">[field.datenumber;frm='mm-dd-yyyy']</div></td> </tr> </table> </td> </tr> </table> </body> </html> index.php <?php require_once('../stockman-v3/tbs_class.php'); require_once('../stockman-v3/config.php'); // Create data $TeamList[0] = array('team'=>'Eagle' ,'total'=>'458'); //{ $TeamList[0]['matches'][] = array('town'=>'London','score'=>'253','date'=>'1999-11-30'); $TeamList[0]['matches'][] = array('town'=>'Paris' ,'score'=>'145','date'=>'2002-07-24'); $TeamList[1] = array('team'=>'Goonies','total'=>'281'); $TeamList[1]['matches'][] = array('town'=>'New-York','score'=>'365','date'=>'2001-12-25'); $TeamList[1]['matches'][] = array('town'=>'Madrid' ,'score'=>'521','date'=>'2004-01-14'); // } $TeamList[2] = array('team'=>'MIB' ,'total'=>'615'); // { $TeamList[2]['matches'][] = array('town'=>'Dallas' ,'score'=>'362','date'=>'2001-01-02'); $TeamList[2]['matches'][] = array('town'=>'Lyon' ,'score'=>'321','date'=>'2002-11-17'); $TeamList[2]['matches'][] = array('town'=>'Washington','score'=>'245','date'=>'2003-08-24'); // } $TBS = new clsTinyButStrong; $TBS->LoadTemplate('index3.html'); // Automatic subblock $TBS->MergeBlock("item",$conn,"SELECT * FROM items"); $TBS->MergeBlock("field",$conn,"SELECT * FROM fields WHERE itemid='[%p1%]' "); $TBS->MergeBlock('teamKEY',$TeamList); // Subblock with a dynamic query //$TBS->MergeBlock('match','array','TeamList[%p1%][matches]'); $TBS->MergeBlock("match",$conn,"SELECT * FROM fields WHERE id='[%p1%]' "); $TBS->Show(); ?> please note what i am trying to do If I was to change $TBS->MergeBlock("field",$conn,"SELECT * FROM fields WHERE itemid='[%p1%]' "); to... $TBS->MergeBlock("field",$conn,"SELECT * FROM fields"); It would show all the items.

    Read the article

  • How to autostart this slide

    - by lchales
    Hello there: first of all i have no idea on coding or anything related, simple question: is there any simple way to tell this code to autostart the slide? at the current moment the images change on click. currently the index page only have one image, what i want is to add a few but without the need to click to see the next one here is the code from my index: <script type="text/javascript"> //<![CDATA[ /* the images preload plugin */ (function($) { $.fn.preload = function(options) { var opts = $.extend({}, $.fn.preload.defaults, options), o = $.meta ? $.extend({}, opts, this.data()) : opts; var c = this.length, l = 0; return this.each(function() { var $i = $(this); $('<img/>').load(function(i){ ++l; if(l == c) o.onComplete(); }).attr('src',$i.attr('src')); }); }; $.fn.preload.defaults = { onComplete : function(){return false;} }; })(jQuery); //]]> </script><script type="text/javascript"> //<![CDATA[ $(function() { var $tf_bg = $('#tf_bg'), $tf_bg_images = $tf_bg.find('img'), $tf_bg_img = $tf_bg_images.eq(0), $tf_thumbs = $('#tf_thumbs'), total = $tf_bg_images.length, current = 0, $tf_content_wrapper = $('#tf_content_wrapper'), $tf_next = $('#tf_next'), $tf_prev = $('#tf_prev'), $tf_loading = $('#tf_loading'); //preload the images $tf_bg_images.preload({ onComplete : function(){ $tf_loading.hide(); init(); } }); //shows the first image and initializes events function init(){ //get dimentions for the image, based on the windows size var dim = getImageDim($tf_bg_img); //set the returned values and show the image $tf_bg_img.css({ width : dim.width, height : dim.height, left : dim.left, top : dim.top }).fadeIn(); //resizing the window resizes the $tf_bg_img $(window).bind('resize',function(){ var dim = getImageDim($tf_bg_img); $tf_bg_img.css({ width : dim.width, height : dim.height, left : dim.left, top : dim.top }); }); //expand and fit the image to the screen $('#tf_zoom').live('click', function(){ if($tf_bg_img.is(':animated')) return false; var $this = $(this); if($this.hasClass('tf_zoom')){ resize($tf_bg_img); $this.addClass('tf_fullscreen') .removeClass('tf_zoom'); } else{ var dim = getImageDim($tf_bg_img); $tf_bg_img.animate({ width : dim.width, height : dim.height, top : dim.top, left : dim.left },350); $this.addClass('tf_zoom') .removeClass('tf_fullscreen'); } } ); //click the arrow down, scrolls down $tf_next.bind('click',function(){ if($tf_bg_img.is(':animated')) return false; scroll('tb'); }); //click the arrow up, scrolls up $tf_prev.bind('click',function(){ if($tf_bg_img.is(':animated')) return false; scroll('bt'); }); //mousewheel events - down / up button trigger the scroll down / up $(document).mousewheel(function(e, delta) { if($tf_bg_img.is(':animated')) return false; if(delta > 0) scroll('bt'); else scroll('tb'); return false; }); //key events - down / up button trigger the scroll down / up $(document).keydown(function(e){ if($tf_bg_img.is(':animated')) return false; switch(e.which){ case 38: scroll('bt'); break; case 40: scroll('tb'); break; } }); } //show next / prev image function scroll(dir){ //if dir is "tb" (top -> bottom) increment current, //else if "bt" decrement it current = (dir == 'tb')?current + 1:current - 1; //we want a circular slideshow, //so we need to check the limits of current if(current == total) current = 0; else if(current < 0) current = total - 1; //flip the thumb $tf_thumbs.flip({ direction : dir, speed : 400, onBefore : function(){ //the new thumb is set here var content = '<span id="tf_zoom" class="tf_zoom"><\/span>'; content +='<img src="' + $tf_bg_images.eq(current).attr('longdesc') + '" alt="Thumb' + (current+1) + '"/>'; $tf_thumbs.html(content); } }); //we get the next image var $tf_bg_img_next = $tf_bg_images.eq(current), //its dimentions dim = getImageDim($tf_bg_img_next), //the top should be one that makes the image out of the viewport //the image should be positioned up or down depending on the direction top = (dir == 'tb')?$(window).height() + 'px':-parseFloat(dim.height,10) + 'px'; //set the returned values and show the next image $tf_bg_img_next.css({ width : dim.width, height : dim.height, left : dim.left, top : top }).show(); //now slide it to the viewport $tf_bg_img_next.stop().animate({ top : dim.top },700); //we want the old image to slide in the same direction, out of the viewport var slideTo = (dir == 'tb')?-$tf_bg_img.height() + 'px':$(window).height() + 'px'; $tf_bg_img.stop().animate({ top : slideTo },700,function(){ //hide it $(this).hide(); //the $tf_bg_img is now the shown image $tf_bg_img = $tf_bg_img_next; //show the description for the new image $tf_content_wrapper.children() .eq(current) .show(); }); //hide the current description $tf_content_wrapper.children(':visible') .hide() } //animate the image to fit in the viewport function resize($img){ var w_w = $(window).width(), w_h = $(window).height(), i_w = $img.width(), i_h = $img.height(), r_i = i_h / i_w, new_w,new_h; if(i_w > i_h){ new_w = w_w; new_h = w_w * r_i; if(new_h > w_h){ new_h = w_h; new_w = w_h / r_i; } } else{ new_h = w_w * r_i; new_w = w_w; } $img.animate({ width : new_w + 'px', height : new_h + 'px', top : '0px', left : '0px' },350); } //get dimentions of the image, //in order to make it full size and centered function getImageDim($img){ var w_w = $(window).width(), w_h = $(window).height(), r_w = w_h / w_w, i_w = $img.width(), i_h = $img.height(), r_i = i_h / i_w, new_w,new_h, new_left,new_top; if(r_w > r_i){ new_h = w_h; new_w = w_h / r_i; } else{ new_h = w_w * r_i; new_w = w_w; } return { width : new_w + 'px', height : new_h + 'px', left : (w_w - new_w) / 2 + 'px', top : (w_h - new_h) / 2 + 'px' }; } }); //]]> </script>

    Read the article

  • CSS list menu; extra padding on rollover of buttons

    - by user1669878
    I have been going crazy trying to figure out why there is extra padding showing up on my navigation buttons when I rollover them. It's only showing up to the left and right of them though. Here's a link to the screenshot of what it looks like: http://i179.photobucket.com/albums/w319/jdauel/Screenshot2012-09-13at25417PM.png I think it has something to do with my CSS but I have no idea anymore. Please help me??? I tried using Firebug to figure it out with no prevail. Here's the code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Farren's Photography</title> <style type="text/css"> html { height: 100%; width: 100%; } body { margin: 0px; } #container { font-family: Georgia, "Times New Roman", Times, serif; font-size: 1.2em; color: #000; background-color: #06F; text-align: left; padding: 0px; height: 650px; width: 960px; margin-right: auto; margin-left: auto; background-image: url(images/background_image.png); background-repeat: no-repeat; margin-top: 45px; } a:link { color: #FFF; } a:visited { color: #FFF; } a:hover { color: #FFF; } #container #logo { } #container #logo #fp-logo { background-image: url(images/logo.png); height: 137px; width: 408px; text-indent: -9999px; display: block; } #logo { height: 137px; width: 408px; position: relative; padding-top: 35px; padding-right: 0px; padding-bottom: 0px; padding-left: 35px; } #main { background-color: #FFF; min-height: 383px; width: 707px; position: relative; left: 217px; top: 16px; right: 36px; bottom: 113px; } #container #navbar { font-family: Georgia, "Times New Roman", Times, serif; font-size: 14px; color: #FFF; text-align: right; height: 45px; background-color: #CC0000; position: relative; top: 8px; bottom: 0px; left: 0px; right: 0px; } #container #navbar ul li a { text-decoration: none; } #container #navbar ul { list-style-type: none; padding-top: 16px; } #container #navbar ul li { display: inline; background-color: #280803; margin: 0px; height: 0px; width: 0px; position: relative; padding-top: 16px; padding-right: 15px; padding-bottom: 17px; padding-left: 15px; } #container #navbar ul li a:link { text-decoration: none; color: #FFF; } #container #navbar ul li a:visited { text-decoration: none; color: #FFF; } #container #navbar ul li a:hover { text-decoration: none; color: #FFF; background-color: #027e8e; padding-top: 16px; padding-right: 15px; padding-bottom: 17px; padding-left: 15px; margin: 0px; } #footer { font-family: Arial, Helvetica, sans-serif; font-size: x-small; height: 28px; position: relative; top: 8px; color: #FFF; font-style: italic; } </style> </head> <body> <div id="container"> <div id="logo"><a href="http://www.farrensphotography.com" title="Farren's Photography" target="_self" id="fp-logo">Farren's Photography</a></div><!-- end logo --> <div id="main"> <div id="content"> </div><!-- end content --> </div><!-- end main --> <div id="navbar"> <ul> <li><a href="index.html" target="_self">Home</a></li> <li><a href="portfolio.html" target="_self">Portfolio</a></li> <li><a href="mystyle.html" target="_self">My Style</a></li> <li><a href="specials.html" target="_self">Specials</a></li> <li><a href="pricing.html" target="_self">Pricing</a></li> <li><a href="contact.html" target="_self">Contact</a></li> </ul> </div> <!-- end navbar --> <div id="footer"> <div id="copyright">All images copyright© Farrens Photography </div><!-- end copyright --> <div id="network">Facebook button </div><!-- end network --> </div><!-- end footer --> </div><!-- end container --> </body> </html>

    Read the article

  • Print a HTML page in landscape mode?

    - by yoz1k
    Is it possible to print a simple page in landscape mode? (without the need for the user to go to printer settings?) <!DOCTYPE html> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <style type="text/css" media="print"/> @page { size: landscape; margin: 2cm; } body { color: red; } </style> <style type="text/css" media="all" > body { font-size: 10pt; font-family: Arial; } table td { padding: 2em; } </style> </head> <body> <table> <tr> <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td> </tr> <tr> <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td> </tr> <tr> <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td> </tr> <tr> <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td> </tr> <tr> <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td> </tr> <tr> <td>a</td><td>b</td><td>c</td><td>d</td><td>e</td><td>f</td><td>g</td><td>h</td><td>i</td><td>j</td><td>k</td><td>l</td><td>m</td><td>n</td><td>o</td><td>p</td><td>q</td><td>r</td><td>s</td><td>t</td><td>u</td><td>v</td><td>w</td><td>x</td><td>y</td><td>z</td> </tr> </table> </body> </html> the solution @page size: landscape didn't help. any ideas?

    Read the article

  • How to Upload a file from client to server using OFBIZ?

    - by SIVAKUMAR.J
    Hi all, Im new to ofbiz.So is my question is have any mistake forgive me for my mistakes.Im new to ofbiz so i did not know some terminologies in ofbiz.Sometimes my question is not clear because of lack of knowledge in ofbiz.So try to understand my question and give me a good solution with respect to my level.Because some solutions are in very high level cannot able to understand for me.So please give the solution with good examples. My problem is i created a project inside the ofbiz/hot-deploy folder namely "productionmgntSystem".Inside the folder "ofbiz\hot-deploy\productionmgntSystem\webapp\productionmgntSystem" i created a .ftl file namely "app_details_1.ftl" .The following are the coding of this file <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> <script TYPE="TEXT/JAVASCRIPT" language=""JAVASCRIPT"> function uploadFile() { //alert("Before calling upload.jsp"); window.location='<@ofbizUrl>testing_service1</@ofbizUrl>' } </script> </head> <!-- <form action="<@ofbizUrl>testing_service1</@ofbizUrl>" enctype="multipart/form-data" name="app_details_frm"> --> <form action="<@ofbizUrl>logout1</@ofbizUrl>" enctype="multipart/form-data" name="app_details_frm"> <center style="height: 299px; "> <table border="0" style="height: 177px; width: 788px"> <tr style="height: 115px; "> <td style="width: 103px; "> <td style="width: 413px; "><h1>APPLICATION DETAILS</h1> <td style="width: 55px; "> </tr> <tr> <td style="width: 125px; ">Application name : </td> <td> <input name="app_name_txt" id="txt_1" value=" " /> </td> </tr> <tr> <td style="width: 125px; ">Excell sheet &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: </td> <td> <input type="file" name="filename"/> </td> </tr> <tr> <td> <!-- <input type="button" name="logout1_cmd" value="Logout" onclick="logout1()"/> --> <input type="submit" name="logout_cmd" value="logout"/> </td> <td> <!-- <input type="submit" name="upload_cmd" value="Submit" /> --> <input type="button" name="upload1_cmd" value="Upload" onclick="uploadFile()"/> </td> </tr> </table> </center> </form> </html> the following coding is present in the file "ofbiz\hot-deploy\productionmgntSystem\webapp\productionmgntSystem\WEB-INF\controller.xml" ...... ....... ........ <request-map uri="testing_service1"> <security https="true" auth="true"/> <event type="java" path="org.ofbiz.productionmgntSystem.web_app_req.WebServices1" invoke="testingService"/> <response name="ok" type="view" value="ok_view"/> <response name="exception" type="view" value="exception_view"/> </request-map> .......... ............ .......... <view-map name="ok_view" type="ftl" page="ok_view.ftl"/> <view-map name="exception_view" type="ftl" page="exception_view.ftl"/> ................ ............. ............. The following are the coding present in the file "ofbiz\hot-deploy\productionmgntSystem\src\org\ofbiz\productionmgntSystem\web_app_req\WebServices1.java" package org.ofbiz.productionmgntSystem.web_app_req; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.IOException; public class WebServices1 { public static String testingService(HttpServletRequest request, HttpServletResponse response) { //int i=0; String result="ok"; System.out.println("\n\n\t*************************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response)- Start"); String contentType=request.getContentType(); System.out.println("\n\n\t*************************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response)- contentType : "+contentType); String str=new String(); // response.setContentType("text/html"); //PrintWriter writer; if ((contentType != null) && (contentType.indexOf("multipart/form-data") >= 0)) { System.out.println("\n\n\t**********************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response) after if (contentType != null)"); try { // writer=response.getWriter(); System.out.println("\n\n\t**********************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response) - try Start"); DataInputStream in = new DataInputStream(request.getInputStream()); int formDataLength = request.getContentLength(); byte dataBytes[] = new byte[formDataLength]; int byteRead = 0; int totalBytesRead = 0; //this loop converting the uploaded file into byte code while (totalBytesRead < formDataLength) { byteRead = in.read(dataBytes, totalBytesRead,formDataLength); totalBytesRead += byteRead; } String file = new String(dataBytes); //for saving the file name String saveFile = file.substring(file.indexOf("filename=\"") + 10); saveFile = saveFile.substring(0, saveFile.indexOf("\n")); saveFile = saveFile.substring(saveFile.lastIndexOf("\\")+ 1,saveFile.indexOf("\"")); int lastIndex = contentType.lastIndexOf("="); String boundary = contentType.substring(lastIndex + 1,contentType.length()); int pos; //extracting the index of file pos = file.indexOf("filename=\""); pos = file.indexOf("\n", pos) + 1; pos = file.indexOf("\n", pos) + 1; pos = file.indexOf("\n", pos) + 1; int boundaryLocation = file.indexOf(boundary, pos) - 4; int startPos = ((file.substring(0, pos)).getBytes()).length; int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length; //creating a new file with the same name and writing the content in new file FileOutputStream fileOut = new FileOutputStream("/"+saveFile); fileOut.write(dataBytes, startPos, (endPos - startPos)); fileOut.flush(); fileOut.close(); System.out.println("\n\n\t**********************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response) - try End"); } catch(IOException ioe) { System.out.println("\n\n\t*********************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response) - Catch IOException"); //ioe.printStackTrace(); return("exception"); } catch(Exception ex) { System.out.println("\n\n\t*********************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response) - Catch Exception"); return("exception"); } } else { System.out.println("\n\n\t********************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response) else part"); result="exception"; } System.out.println("\n\n\t*************************************\n\tInside WebServices1.testingService(HttpServletRequest request, HttpServletResponse response)- End"); return(result); } } I want to upload a file to the server.The file is get from user "<input type="file"..> tag in the "app_details_1.ftl" file & it is updated into the server by using the method "testingService(HttpServletRequest request, HttpServletResponse response)" in the class "WebServices1".But the file is not uploaded. Give me a good solution for uploading a file to the server. Thanks & Regards, Sivakumar.J

    Read the article

  • JBoss https on port other than 8080 not working

    - by MilindaD
    We have a server with two JBoss instances where one runs on 8080, the other on 8081. We need to have HTTPS enabled for the 8081 server, firstly we tried enabling https on the 8080 port instance by generating the keystore and editing the server.xml and it successfully worked. However when we tried the same thing for 8081 it did not, note that we removed https for the 8080 server first before enabling it for 8081. This is what was used for both server.xml for 8080 and 8081. The only difference was that the port was changed from 8080 to 8081 when trying to enable https for 8081 port instance. What am I doing wrong and what needs to be changed? NOTE : When I meant enabled for 8080 I meant when you visit https:// URL:8484 you will actually be visiting the 8080 port instance. However when ssl is enabled for 8081 and I visit https:// URL:8484 I get that the web page is unavailable. COMMENTLESS VERSION <Server> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <Listener className="org.apache.catalina.core.JasperListener" /> <Service name="jboss.web"> <!-- https --> <Connector port="8080" address="${jboss.bind.address}" maxThreads="350" maxHttpHeaderSize="8192" emptySessionPath="true" protocol="HTTP/1.1" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" compression="on" ompressableMimeType="text/html,text/css,text/javascript,application/json,text/xml,text/plain,application/x-javascript,application/javascript"/> <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" address="${jboss.bind.address}" keystoreFile="${jboss.server.home.dir}/conf/supun1.keystore" keystorePass="aaaaaa" truststoreFile="${jboss.server.home.dir}/conf/supun1.keystore" truststorePass="aaaaaa" /> <!-- https1 --> <Connector port="8009" address="${jboss.bind.address}" protocol="AJP/1.3" emptySessionPath="true" enableLookups="false" redirectPort="8443" /> <Engine name="jboss.web" defaultHost="localhost" jvmRoute="khms1"> <Realm className="org.jboss.web.tomcat.security.JBossSecurityMgrRealm" certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping" allRolesMode="authOnly" /> <Host name="localhost" autoDeploy="false" deployOnStartup="false" deployXML="false" configClass="org.jboss.web.tomcat.security.config.JBossContextConfig" > <Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn" /> <Valve className="org.jboss.web.tomcat.service.jca.CachedConnectionValve" cachedConnectionManagerObjectName="jboss.jca:service=CachedConnectionManager" transactionManagerObjectName="jboss:service=TransactionManager" /> </Host> </Engine> </Service> </Server> WITH COMMENTS VERSION <Server> <!--APR library loader. Documentation at /docs/apr.html --> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --> <Listener className="org.apache.catalina.core.JasperListener" /> <!-- Use a custom version of StandardService that allows the connectors to be started independent of the normal lifecycle start to allow web apps to be deployed before starting the connectors. --> <Service name="jboss.web"> <!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL HTTP/1.1 Connector on port 8080 --> <Connector port="8080" address="${jboss.bind.address}" maxThreads="350" maxHttpHeaderSize="8192" emptySessionPath="true" protocol="HTTP/1.1" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" compression="on" ompressableMimeType="text/html,text/css,text/javascript,application/json,text/xml,text/plain,application/x-javascript,application/javascript"/> <!-- Define a SSL HTTP/1.1 Connector on port 8443 This connector uses the JSSE configuration, when using APR, the connector should be using the OpenSSL style configuration described in the APR documentation --> <!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="${jboss.server.home.dir}/conf/zara.keystore" keystorePass="zara2010" clientAuth="false" sslProtocol="TLS" compression="on" /> --> <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" address="${jboss.bind.address}" keystoreFile="${jboss.server.home.dir}/conf/supun1.keystore" keystorePass="aaaaaa" truststoreFile="${jboss.server.home.dir}/conf/supun1.keystore" truststorePass="aaaaaa" /> <!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" address="${jboss.bind.address}" protocol="AJP/1.3" emptySessionPath="true" enableLookups="false" redirectPort="8443" /> <Engine name="jboss.web" defaultHost="localhost" jvmRoute="khms1"> <!-- The JAAS based authentication and authorization realm implementation that is compatible with the jboss 3.2.x realm implementation. - certificatePrincipal : the class name of the org.jboss.security.auth.certs.CertificatePrincipal impl used for mapping X509[] cert chains to a Princpal. - allRolesMode : how to handle an auth-constraint with a role-name=*, one of strict, authOnly, strictAuthOnly + strict = Use the strict servlet spec interpretation which requires that the user have one of the web-app/security-role/role-name + authOnly = Allow any authenticated user + strictAuthOnly = Allow any authenticated user only if there are no web-app/security-roles --> <Realm className="org.jboss.web.tomcat.security.JBossSecurityMgrRealm" certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping" allRolesMode="authOnly" /> <!-- A subclass of JBossSecurityMgrRealm that uses the authentication behavior of JBossSecurityMgrRealm, but overrides the authorization checks to use JACC permissions with the current java.security.Policy to determine authorized access. - allRolesMode : how to handle an auth-constraint with a role-name=*, one of strict, authOnly, strictAuthOnly + strict = Use the strict servlet spec interpretation which requires that the user have one of the web-app/security-role/role-name + authOnly = Allow any authenticated user + strictAuthOnly = Allow any authenticated user only if there are no web-app/security-roles <Realm className="org.jboss.web.tomcat.security.JaccAuthorizationRealm" certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping" allRolesMode="authOnly" /> --> <Host name="localhost" autoDeploy="false" deployOnStartup="false" deployXML="false" configClass="org.jboss.web.tomcat.security.config.JBossContextConfig" > <!-- Uncomment to enable request dumper. This Valve "logs interesting contents from the specified Request (before processing) and the corresponding Response (after processing). It is especially useful in debugging problems related to headers and cookies." --> <!-- <Valve className="org.apache.catalina.valves.RequestDumperValve" /> --> <!-- Access logger --> <!-- <Valve className="org.apache.catalina.valves.AccessLogValve" prefix="localhost_access_log." suffix=".log" pattern="common" directory="${jboss.server.log.dir}" resolveHosts="false" /> --> <!-- Uncomment to enable single sign-on across web apps deployed to this host. Does not provide SSO across a cluster. If this valve is used, do not use the JBoss ClusteredSingleSignOn valve shown below. A new configuration attribute is available beginning with release 4.0.4: cookieDomain configures the domain to which the SSO cookie will be scoped (i.e. the set of hosts to which the cookie will be presented). By default the cookie is scoped to "/", meaning the host that presented it. Set cookieDomain to a wider domain (e.g. "xyz.com") to allow an SSO to span more than one hostname. --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Uncomment to enable single sign-on across web apps deployed to this host AND to all other hosts in the cluster. If this valve is used, do not use the standard Tomcat SingleSignOn valve shown above. Valve uses a JBossCache instance to support SSO credential caching and replication across the cluster. The JBossCache instance must be configured separately. By default, the valve shares a JBossCache with the service that supports HttpSession replication. See the "jboss-web-cluster-service.xml" file in the server/all/deploy directory for cache configuration details. Besides the attributes supported by the standard Tomcat SingleSignOn valve (see the Tomcat docs), this version also supports the following attributes: cookieDomain see above treeCacheName JMX ObjectName of the JBossCache MBean used to support credential caching and replication across the cluster. If not set, the default value is "jboss.cache:service=TomcatClusteringCache", the standard ObjectName of the JBossCache MBean used to support session replication. --> <Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn" /> <!-- Check for unclosed connections and transaction terminated checks in servlets/jsps. Important: The dependency on the CachedConnectionManager in META-INF/jboss-service.xml must be uncommented, too --> <Valve className="org.jboss.web.tomcat.service.jca.CachedConnectionValve" cachedConnectionManagerObjectName="jboss.jca:service=CachedConnectionManager" transactionManagerObjectName="jboss:service=TransactionManager" /> </Host> </Engine> </Service> </Server>

    Read the article

  • Oracle Support Master Note for Troubleshooting Advanced Queuing and Oracle Streams Propagation Issues (Doc ID 233099.1)

    - by faye.todd(at)oracle.com
    Master Note for Troubleshooting Advanced Queuing and Oracle Streams Propagation Issues (Doc ID 233099.1) Copyright (c) 2010, Oracle Corporation. All Rights Reserved. In this Document  Purpose  Last Review Date  Instructions for the Reader  Troubleshooting Details     1. Scope and Application      2. Definitions and Classifications     3. How to Use This Guide     4. Basic AQ Propagation Troubleshooting     5. Additional Troubleshooting Steps for AQ Propagation of User-Enqueued and Dequeued Messages     6. Additional Troubleshooting Steps for Propagation in an Oracle Streams Environment     7. Performance Issues  References Applies to: Oracle Server - Enterprise Edition - Version: 8.1.7.0 to 11.2.0.2 - Release: 8.1.7 to 11.2Information in this document applies to any platform. Purpose This document presents a step-by-step methodology for troubleshooting and resolving problems with Advanced Queuing Propagation in both Streams and basic Advanced Queuing environments. It also serves as a master reference for other more specific notes on Oracle Streams Propagation and Advanced Queuing Propagation issues. Last Review Date December 20, 2010 Instructions for the Reader A Troubleshooting Guide is provided to assist in debugging a specific issue. When possible, diagnostic tools are included in the document to assist in troubleshooting. Troubleshooting Details 1. Scope and Application This note is intended for Database Administrators of Oracle databases where issues are being encountered with propagating messages between advanced queues, whether the queues are used for user-created messaging systems or for Oracle Streams. It contains troubleshooting steps and links to notes for further problem resolution.It can also be used a template to document a problem when it is necessary to engage Oracle Support Services. Knowing what is NOT happening can frequently speed up the resolution process by focusing solely on the pertinent problem area. This guide is divided into five parts: Section 2: Definitions and Classifications (discusses the different types and features of propagations possible - helpful for understanding the rest of the guide) Section 3: How to Use this Guide (to be used as a start part for determining the scope of the problem and what sections to consult) Section 4. Basic AQ propagation troubleshooting (applies to both AQ propagation of user enqueued and dequeued messages as well as Oracle Streams propagations) Section 5. Additional troubleshooting steps for AQ propagation of user enqueued and dequeued messages Section 6. Additional troubleshooting steps for Oracle Streams propagation Section 7. Performance issues 2. Definitions and Classifications Given the potential scope of issues that can be encountered with AQ propagation, the first recommended step is to do some basic diagnosis to determine the type of problem that is being encountered. 2.1. What Type of Propagation is Being Used? 2.1.1. Buffered Messaging For an advanced queue, messages can be maintained on disk (persistent messaging) or in memory (buffered messaging). To determine if a queue is buffered or not, reference the GV_$BUFFERED_QUEUES view. If the queue does not appear in this view, it is persistent. 2.1.2. Propagation mode - queue-to-dblink vs queue-to-queue As of 10.2, an AQ propagation can also be defined as queue-to-dblink, or queue-to-queue: queue-to-dblink: The propagation delivers messages or events from the source queue to all subscribing queues at the destination database identified by the dblink. A single propagation schedule is used to propagate messages to all subscribing queues. Hence any changes made to this schedule will affect message delivery to all the subscribing queues. This mode does not support multiple propagations from the same source queue to the same target database. queue-to-queue: Added in 10.2, this propagation mode delivers messages or events from the source queue to a specific destination queue identified on the database link. This allows the user to have fine-grained control on the propagation schedule for message delivery. This new propagation mode also supports transparent failover when propagating to a destination Oracle RAC system. With queue-to-queue propagation, you are no longer required to re-point a database link if the owner instance of the queue fails on Oracle RAC. This mode supports multiple propagations to the same target database if the target queues are different. The default is queue-to-dblink. To verify if queue-to-queue propagation is being used, in non-Streams environments query DBA_QUEUE_SCHEDULES.DESTINATION - if a remote queue is listed along with the remote database link, then queue-to-queue propagation is being used. For Streams environments, the DBA_PROPAGATION.QUEUE_TO_QUEUE column can be checked.See the following note for a method to switch between the two modes:Document 827473.1 How to alter propagation from queue-to-queue to queue-to-dblink 2.1.3. Combined Capture and Apply (CCA) for Streams In 11g Oracle Streams environments, an optimization called Combined Capture and Apply (CCA) is implemented by default when possible. Although a propagation is configured in this case, Streams does not use it; instead it passes information directly from capture to an apply receiver. To see if CCA is in use: COLUMN CAPTURE_NAME HEADING 'Capture Name' FORMAT A30COLUMN OPTIMIZATION HEADING 'CCA Mode?' FORMAT A10SELECT CAPTURE_NAME, DECODE(OPTIMIZATION,0, 'No','Yes') OPTIMIZATIONFROM V$STREAMS_CAPTURE; Also, see the following note:Document 463820.1 Streams Combined Capture and Apply in 11g 2.2. Queue Table Compatibility There are three types of queue table compatibility. In more recent databases, queue tables may be present in all three modes of compatibility: 8.0 - earliest version, deprecated in 10.2 onwards 8.1 - support added for RAC, asynchronous notification, secure queues, queue level access control, rule-based subscribers, separate storage of history information 10.0 - if the database is in 10.1-compatible mode, then the default value for queue table compatibility is 10.0 2.3. Single vs Multiple Consumer Queue Tables If more than one recipient can dequeue a message from a queue, then its queue table is multiple consumer. You can propagate messages from a multiple-consumer queue to a single-consumer queue. Propagation from a single-consumer queue to a multiple-consumer queue is not possible. 3. How to Use This Guide 3.1. Are Messages Being Propagated at All, or is the Propagation Just Slow? Run the following query on the source database for the propagation (assuming that it is running): select TOTAL_NUMBER from DBA_QUEUE_SCHEDULES where QNAME='<source_queue_name>'; If TOTAL_NUMBER is increasing, then propagation is most likely functioning, although it may be slow. For performance issues, see Section 7. 3.2. Propagation Between Persistent User-Created Queues See Sections 4 and 5 (and optionally Section 6 if performance is an issue). 3.3. Propagation Between Buffered User-Created Queues See Sections 4, 5, and 6 (and optionally Section 7 if performance is an issue). 3.4. Propagation between Oracle Streams Queues (without Combined Capture and Apply (CCA) Optimization) See Sections 4 and 6 (and optionally Section 7 if performance is an issue). 3.5. Propagation between Oracle Streams Queues (with Combined Capture and Apply (CCA) Optimization) Although an AQ propagation is not used directly in this case, some characteristics of the message transfer are inferred from the propagation parameters used. Some parts of Sections 4 and 6 still apply. 3.6. Messaging Gateway Propagations This note does not apply to Messaging Gateway propagations. 4. Basic AQ Propagation Troubleshooting 4.1. Double-check Your Code Make sure that you are consistent in your usage of the database link(s) names, queue names, etc. It may be useful to plot a diagram of which queues are connected via which database links to make sure that the logical structure is correct. 4.2. Verify that Job Queue Processes are Running 4.2.1. Versions 10.2 and Lower - DBA_JOBS Package For versions 10.2 and lower, a scheduled propagation is managed by DBMS_JOB package. The propagation is performed by job queue process background processes. Therefore we need to verify that there are sufficient processes available for the propagation process. We should have at least 4 job queue processes running and preferably more depending on the number of other jobs running in the database. It should be noted that for AQ specific work, AQ will only ever use half of the job queue processes available.An issue caused by an inadequate job queue processes parameter setting is described in the following note:Document 298015.1 Kwqjswproc:Excep After Loop: Assigning To Self 4.2.1.1. Job Queue Processes in Initalization Parameter File The parameter JOB_QUEUE_PROCESSES in the init.ora/spfile should be > 0. The value can be changed dynamically via connect / as sysdbaalter system set JOB_QUEUE_PROCESSES=10; 4.2.1.2. Job Queue Processes in Memory The following command will show how many job queue processes are currentlyin use by this instance (this may be different than what is in the init.ora/spfile): connect / as sysdbashow parameter job; 4.2.1.3. OS PIDs Corresponding to Job Queue Processes Identify the operating system process ids (spids) of job queue processes involved in propagation via select p.SPID, p.PROGRAM from V$PROCESS p, DBA_JOBS_RUNNING jr, V$SESSION s, DBA_JOBS j where s.SID=jr.SID and s.PADDR=p.ADDR and jr.JOB=j.JOBand j.WHAT like '%sys.dbms_aqadm.aq$_propaq(job)%'; and these SPIDs can be used to check at the operating system level that they exist.In 8i a job queue process will have a name similar to: ora_snp1_<instance_name>.In 9i onwards you will see a coordinator process: ora_cjq0_ and multiple slave processes: ora_jnnn_<instance_name>, where nnn is an integer between 1 and 999. 4.2.2. Version 11.1 and Above - Oracle Scheduler In version 11.1 and above, Oracle Scheduler is used to perform AQ and Streams propagations. Oracle Scheduler automatically tunes the number of slave processes for these jobs based on the load on the computer system, and the JOB_QUEUE_PROCESSES initialization parameter is only used to specify the maximum number of slave processes. Therefore, the JOB_QUEUE_PROCESSES initialization parameter does not need to be set (it defaults to a very high number), unless you want to limit the number of slaves that can be created. If JOB_QUEUE_PROCESSES = 0, no propagation jobs will run.See the following note for a discussion of Oracle Streams 11g and Oracle Scheduler:Document 1083608.1 11g Streams and Oracle Scheduler 4.2.2.1. Job Queue Processes in Initalization Parameter File The parameter JOB_QUEUE_PROCESSES in the init.ora/spfile should be > 0, and preferably be left at its default value. The value can be changed dynamically via connect / as sysdbaalter system set JOB_QUEUE_PROCESSES=10; To set the JOB_QUEUE_PROCESSES parameter to its default value, run: connect / as sysdbaalter system reset JOB_QUEUE_PROCESSES; and then bounce the instance. 4.2.2.2. Job Queue Processes in Memory The following command will show how many job queue processes are currently in use by this instance (this may be different than what is in the init.ora/spfile): connect / as sysdbashow parameter job; 4.2.2.3. OS PIDs Corresponding to Job Queue Processes Identify the operating system process ids (SPIDs) of job queue processes involved in propagation via col PROGRAM for a30select p.SPID, p.PROGRAM, j.JOB_namefrom v$PROCESS p, DBA_SCHEDULER_RUNNING_JOBS jr, V$SESSION s, DBA_SCHEDULER_JOBS j where s.SID=jr.SESSION_ID and s.PADDR=p.ADDRand jr.JOB_name=j.JOB_NAME and j.JOB_NAME like '%AQ_JOB$_%'; and these SPIDs can be used to check at the operating system level that they exist.You will see a coordinator process: ora_cjq0_ and multiple slave processes: ora_jnnn_<instance_name>, where nnn is an integer between 1 and 999. 4.3. Check the Alert Log and Any Associated Trace Files The first place to check for propagation failures is the alert logs at all sites (local and if relevant all remote sites). When a job queue process attempts to execute a schedule and fails it will always write an error stack to the alert log. This error stack will also be written in a job queue process trace file, which will be written to the BACKGROUND_DUMP_DEST location for 10.2 and below, and in the DIAGNOSTIC_DEST location for 11g. The fact that errors are written to the alert log demonstrates that the schedule is executing. This means that the problem could be with the set up of the schedule. In this example the ORA-02068 demonstrates that the failure was at the remote site. Further investigation revealed that the remote database was not open, hence the ORA-03114 error. Starting the database resolved the problem. Thu Feb 14 10:40:05 2002 Propagation Schedule for (AQADM.MULTIPLEQ, SHANE816.WORLD) encountered following error:ORA-04052: error occurred when looking up Remote object [email protected]: error occurred at recursive SQL level 4ORA-02068: following severe error from SHANE816ORA-03114: not connected to ORACLEORA-06512: at "SYS.DBMS_AQADM_SYS", line 4770ORA-06512: at "SYS.DBMS_AQADM", line 548ORA-06512: at line 1 Other potential errors that may be written to the alert log can be found in the following notes:Document 827184.1 AQ Propagation with CLOB data types Fails with ORA-22990 (11.1)Document 846297.1 AQ Propagation Fails : ORA-00600[kope2upic2954] or Ora-00600[Kghsstream_copyn] (10.2, 11.1)Document 731292.1 ORA-25215 Reported on Local Propagation When Using Transformation with ANYDATA queue tables (10.2, 11.1, 11.2)Document 365093.1 ORA-07445 [kwqppay2aqe()+7360] Reported on Propagation of a Transformed Message (10.1, 10.2)Document 219416.1 Advanced Queuing Propagation Fails with ORA-22922 (9.0)Document 1203544.1 AQ Propagation Aborted with ORA-600 [ociksin: invalid status] on SYS.DBMS_AQADM_SYS.AQ$_PROPAGATION_PROCEDURE After Upgrade (11.1, 11.2)Document 1087324.1 ORA-01405 ORA-01422 reported by Advanced Queuing Propagation schedules after RAC reconfiguration (10.2)Document 1079577.1 Advanced Queuing Propagation Fails With "ORA-22370 incorrect usage of method" (9.2, 10.2, 11.1, 11.2)Document 332792.1 ORA-04061 error relating to SYS.DBMS_PRVTAQIP reported when setting up Statspack (8.1, 9.0, 9.2, 10.1)Document 353325.1 ORA-24056: Internal inconsistency for QUEUE <queue_name> and destination <dblink> (8.1, 9.0, 9.2, 10.1, 10.2, 11.1, 11.2)Document 787367.1 ORA-22275 reported on Propagating Messages with LOB component when propagating between 10.1 and 10.2 (10.1, 10.2)Document 566622.1 ORA-22275 when propagating >4K AQ$_JMS_TEXT_MESSAGEs from 9.2.0.8 to 10.2.0.1 (9.2, 10.1)Document 731539.1 ORA-29268: HTTP client error 401 Unauthorized Error when the AQ Servlet attempts to Propagate a message via HTTP (9.0, 9.2, 10.1, 10.2, 11.1)Document 253131.1 Concurrent Writes May Corrupt LOB Segment When Using Auto Segment Space Management (ORA-1555) (9.2)Document 118884.1 How to unschedule a propagation schedule stuck in pending stateDocument 222992.1 DBMS_AQADM.DISABLE_PROPAGATION_SCHEDULE Returns ORA-24082Document 282987.1 Propagated Messages marked UNDELIVERABLE after Drop and Recreate Of Remote QueueDocument 1204080.1 AQ Propagation Failing With ORA-25329 After Upgraded From 8i or 9i to 10g or 11g.Document 1233675.1 AQ Propagation stops after upgrade to 11.2.0.1 ORA-30757 4.3.1. Errors Related to Incorrect Network Configuration The most common propagation errors result from an incorrect network configuration. The list below contains common errors caused by tnsnames.ora file or database links being configured incorrectly: - ORA-12154: TNS:could not resolve service name- ORA-12505: TNS:listener does not currently know of SID given in connect descriptor- ORA-12514: TNS:listener could not resolve SERVICE_NAME - ORA-12541: TNS-12541 TNS:no listener 4.4. Check the Database Links Exist and are Functioning Correctly For schedules to remote databases confirm the database link exists via. SQL> col DBLINK for a45SQL> select QNAME, NVL(REGEXP_SUBSTR(DESTINATION, '[^@]+', 1, 2), DESTINATION) dblink2 from DBA_QUEUE_SCHEDULES3 where MESSAGE_DELIVERY_MODE = 'PERSISTENT';QNAME DBLINK------------------------------ ---------------------------------------------MY_QUEUE ORCL102B.WORLD Connect as the owner of the link and select across it to verify it works and connects to the database we expect. i.e. select * from ALL_QUEUES@ ORCL102B.WORLD; You need to ensure that the userid that scheduled the propagation (using DBMS_AQADM.SCHEDULE_PROPAGATION or DBMS_PROPAGATION_ADM.CREATE_PROPAGATION if using Streams) has access to the database link for the destination. 4.5. Has Propagation Been Correctly Scheduled? Check that the propagation schedule has been created and that a job queue process has been assigned. Look for the entry in DBA_QUEUE_SCHEDULES and SYS.AQ$_SCHEDULES for your schedule. For 10g and below, check that it has a JOBNO entry in SYS.AQ$_SCHEDULES, and that there is an entry in DBA_JOBS with that JOBNO. For 11g and above, check that the schedule has a JOB_NAME entry in SYS.AQ$_SCHEDULES, and that there is an entry in DBA_SCHEDULER_JOBS with that JOB_NAME. Check the destination is as intended and spelled correctly. SQL> select SCHEMA, QNAME, DESTINATION, SCHEDULE_DISABLED, PROCESS_NAME from DBA_QUEUE_SCHEDULES;SCHEMA QNAME DESTINATION S PROCESS------- ---------- ------------------ - -----------AQADM MULTIPLEQ AQ$_LOCAL N J000 AQ$_LOCAL in the destination column shows that the queue to which we are propagating to is in the same database as the source queue. If the propagation was to a remote (different) database, a database link will be in the DESTINATION column. The entry in the SCHEDULE_DISABLED column, N, means that the schedule is NOT disabled. If Y (yes) appears in this column, propagation is disabled and the schedule will not be executed. If not using Oracle Streams, propagation should resume once you have enabled the schedule by invoking DBMS_AQADM.ENABLE_PROPAGATION_SCHEDULE (for 10.2 Oracle Streams and above, the DBMS_PROPAGATION_ADM.START_PROPAGATION procedure should be used). The PROCESS_NAME is the name of the job queue process currently allocated to execute the schedule. This process is allocated dynamically at execution time. If the PROCESS_NAME column is null (empty) the schedule is not currently executing. You may need to execute this statement a number of times to verify if a process is being allocated. If a process is at some time allocated to the schedule, it is attempting to execute. SQL> select SCHEMA, QNAME, LAST_RUN_DATE, NEXT_RUN_DATE from DBA_QUEUE_SCHEDULES;SCHEMA QNAME LAST_RUN_DATE NEXT_RUN_DATE------ ----- ----------------------- ----------------------- AQADM MULTIPLEQ 13-FEB-2002 13:18:57 13-FEB-2002 13:20:30 In 11g, these dates are expressed in TIMESTAMP WITH TIME ZONE datatypes. If the NEXT_RUN_DATE and NEXT_RUN_TIME columns are null when this statement is executed, the scheduled propagation is currently in progress. If they never change it would suggest that the schedule itself is never executing. If the next scheduled execution is too far away, change the NEXT_TIME parameter of the schedule so that schedules are executed more frequently (assuming that the window is not set to be infinite). Parameters of a schedule can be changed using the DBMS_AQADM.ALTER_PROPAGATION_SCHEDULE call. In 10g and below, scheduling propagation posts a job in the DBA_JOBS view. The columns are more or less the same as DBA_QUEUE_SCHEDULES so you just need to recognize the job and verify that it exists. SQL> select JOB, WHAT from DBA_JOBS where WHAT like '%sys.dbms_aqadm.aq$_propaq(job)%';JOB WHAT---- ----------------- 720 next_date := sys.dbms_aqadm.aq$_propaq(job); For 11g, scheduling propagation posts a job in DBA_SCHEDULER_JOBS instead: SQL> select JOB_NAME from DBA_SCHEDULER_JOBS where JOB_NAME like 'AQ_JOB$_%';JOB_NAME------------------------------AQ_JOB$_41 If no job exists, check DBA_QUEUE_SCHEDULES to make sure that the schedule has not been disabled. For 10g and below, the job number is dynamic for AQ propagation schedules. The procedure that is executed to expedite a propagation schedule runs, removes itself from DBA_JOBS, and then reposts a new job for the next scheduled propagation. The job number should therefore always increment unless the schedule has been set up to run indefinitely. 4.6. Is the Schedule Executing but Failing to Complete? Run the following query: SQL> select FAILURES, LAST_ERROR_MSG from DBA_QUEUE_SCHEDULES;FAILURES LAST_ERROR_MSG------------ -----------------------1 ORA-25207: enqueue failed, queue AQADM.INQ is disabled from enqueueingORA-02063: preceding line from SHANE816 The failures column shows how many times we have attempted to execute the schedule and failed. Oracle will attempt to execute the schedule 16 times after which it will be removed from the DBA_JOBS or DBA_SCHEDULER_JOBS view and the schedule will become disabled. The column DBA_QUEUE_SCHEDULES.SCHEDULE_DISABLED will show 'Y'. For 11g and above, the DBA_SCHEDULER_JOBS.STATE column will show 'BROKEN' for the job corresponding to DBA_QUEUE_SCHEDULES.JOB_NAME. Prior to 10g the back off algorithm for failures was exponential, whereas from 10g onwards it is linear. The propagation will become disabled on the 17th attempt. Only the last execution failure will be reflected in the LAST_ERROR_MSG column. That is, if the schedule fails 5 times for 5 different reasons, only the last set of errors will be recorded in DBA_QUEUE_SCHEDULES. Any errors need to be resolved to allow propagation to continue. If propagation has also become disabled due to 17 failures, first resolve the reason for the error and then re-enable the schedule using the DBMS_AQADM.ENABLE_PROPAGATION_SCHEDULE procedure, or DBMS_PROPAGATION_ADM.START_PROPAGATION if using 10.2 or above Oracle Streams. As soon as the schedule executes successfully the error message entries will be deleted. Oracle does not keep a history of past failures. However, when using Oracle Streams, the errors will be retained in the DBA_PROPAGATION view even after the schedule resumes successfully. See the following note for instructions on how to clear out the errors from the DBA_PROPAGATION view:Document 808136.1 How to clear the old errors from DBA_PROPAGATION view?If a schedule is active and no errors are being reported then the source queue may not have any messages to be propagated. 4.7. Do the Propagation Notification Queue Table and Queue Exist? Check to see that the propagation notification queue table and queue exist and are enabled for enqueue and dequeue. Propagation makes use of the propagation notification queue for handling propagation run-time events, and the messages in this queue are stored in a SYS-owned queue table. This queue should never be stopped or dropped and the corresponding queue table never be dropped. 10g and belowThe propagation notification queue table is of the format SYS.AQ$_PROP_TABLE_n, where 'n' is the RAC instance number, i.e. '1' for a non-RAC environment. This queue and queue table are created implicitly when propagation is first scheduled. If propagation has been scheduled and these objects do not exist, try unscheduling and rescheduling propagation. If they still do not exist contact Oracle Support. SQL> select QUEUE_TABLE from DBA_QUEUE_TABLES2 where QUEUE_TABLE like '%PROP_TABLE%' and OWNER = 'SYS';QUEUE_TABLE------------------------------AQ$_PROP_TABLE_1SQL> select NAME, ENQUEUE_ENABLED, DEQUEUE_ENABLED2 from DBA_QUEUES where owner='SYS'3 and QUEUE_TABLE like '%PROP_TABLE%';NAME ENQUEUE DEQUEUE------------------------------ ------- -------AQ$_PROP_NOTIFY_1 YES YESAQ$_AQ$_PROP_TABLE_1_E NO NO If the AQ$_PROP_NOTIFY_1 queue is not enabled for enqueue or dequeue, it should be so enabled using DBMS_AQADM.START_QUEUE. However, the exception queue AQ$_AQ$_PROP_TABLE_1_E should not be enabled for enqueue or dequeue.11g and aboveThe propagation notification queue table is of the format SYS.AQ_PROP_TABLE, and is created when the database is created. If they do not exist, contact Oracle Support. SQL> select QUEUE_TABLE from DBA_QUEUE_TABLES2 where QUEUE_TABLE like '%PROP_TABLE%' and OWNER = 'SYS';QUEUE_TABLE------------------------------AQ_PROP_TABLESQL> select NAME, ENQUEUE_ENABLED, DEQUEUE_ENABLED2 from DBA_QUEUES where owner='SYS'3 and QUEUE_TABLE like '%PROP_TABLE%';NAME ENQUEUE DEQUEUE------------------------------ ------- -------AQ_PROP_NOTIFY YES YESAQ$_AQ_PROP_TABLE_E NO NO If the AQ_PROP_NOTIFY queue is not enabled for enqueue or dequeue, it should be so enabled using DBMS_AQADM.START_QUEUE. However, the exception queue AQ$_AQ$_PROP_TABLE_E should not be enabled for enqueue or dequeue. 4.8. Does the Remote Queue Exist and is it Enabled for Enqueueing? Check that the remote queue the propagation is transferring messages to exists and is enabled for enqueue: SQL> select DESTINATION from USER_QUEUE_SCHEDULES where QNAME = 'OUTQ';DESTINATION-----------------------------------------------------------------------------"AQADM"."INQ"@M2V102.ESSQL> select OWNER, NAME, ENQUEUE_ENABLED, DEQUEUE_ENABLED from [email protected];OWNER NAME ENQUEUE DEQUEUE-------- ------ ----------- -----------AQADM INQ YES YES 4.9. Do the Target and Source Database Charactersets Differ? If a message fails to propagate, check the database charactersets of the source and target databases. Investigate whether the same message can propagate between the databases with the same characterset or it is only a particular combination of charactersets which causes a problem. 4.10. Check the Queue Table Type Agreement Propagation is not possible between queue tables which have types that differ in some respect. One way to determine if this is the case is to run the DBMS_AQADM.VERIFY_QUEUE_TYPES procedure for the two queues that the propagation operates on. If the types do not agree, DBMS_AQADM.VERIFY_QUEUE_TYPES will return '0'.For AQ propagation between databases which have different NLS_LENGTH_SEMANTICS settings, propagation will not work, unless the queues are Oracle Streams ANYDATA queues.See the following notes for issues caused by lack of type agreement:Document 1079577.1 Advanced Queuing Propagation Fails With "ORA-22370: incorrect usage of method"Document 282987.1 Propagated Messages marked UNDELIVERABLE after Drop and Recreate Of Remote QueueDocument 353754.1 Streams Messaging Propagation Fails between Single and Multi-byte Charactersets when using Chararacter Length Semantics in the ADT 4.11. Enable Propagation Tracing 4.11.1. System Level This is set it in the init.ora/spfile as follows: event="24040 trace name context forever, level 10" and restart the instanceThis event cannot be set dynamically with an alter system command until version 10.2: SQL> alter system set events '24040 trace name context forever, level 10'; To unset the event: SQL> alter system set events '24040 trace name context off'; Debugging information will be logged to job queue trace file(s) (jnnn) as propagation takes place. You can check the trace file for errors, and for statements indicating that messages have been sent. For the most part the trace information is understandable. This trace should also be uploaded to Oracle Support if a service request is created. 4.11.2. Attaching to a Specific Process We can also attach to an existing job queue processes that is running a propagation schedule and trace it individually using the oradebug utility, as follows:10.2 and below connect / as sysdbaselect p.SPID, p.PROGRAM from v$PROCESS p, DBA_JOBS_RUNNING jr, V$SESSION s, DBA_JOBS j where s.SID=jr.SID and s.PADDR=p.ADDR and jr.JOB=j.JOB and j.WHAT like '%sys.dbms_aqadm.aq$_propaq(job)%';-- For the process id (SPID) attach to it via oradebug and generate the following traceoradebug setospid <SPID>oradebug unlimitoradebug Event 10046 trace name context forever, level 12oradebug Event 24040 trace name context forever, level 10-- Trace the process for 5 minutesoradebug Event 10046 trace name context offoradebug Event 24040 trace name context off-- The following command returns the pathname/filename to the file being written tooradebug tracefile_name 11g connect / as sysdbacol PROGRAM for a30select p.SPID, p.PROGRAM, j.JOB_NAMEfrom v$PROCESS p, DBA_SCHEDULER_RUNNING_JOBS jr, V$SESSION s, DBA_SCHEDULER_JOBS j where s.SID=jr.SESSION_ID and s.PADDR=p.ADDR and jr.JOB_NAME=j.JOB_NAME and j.JOB_NAME like '%AQ_JOB$_%';-- For the process id (SPID) attach to it via oradebug and generate the following traceoradebug setospid <SPID>oradebug unlimitoradebug Event 10046 trace name context forever, level 12oradebug Event 24040 trace name context forever, level 10-- Trace the process for 5 minutesoradebug Event 10046 trace name context offoradebug Event 24040 trace name context off-- The following command returns the pathname/filename to the file being written tooradebug tracefile_name 4.11.3. Further Tracing The previous tracing steps only trace the job queue process executing the propagation on the source. At times it is useful to trace the propagation receiver process (the session which is enqueueing the messages into the target queue) on the target database which is associated with the job queue process on the source database.These following queries provide ways of identifying the processes involved in propagation so that you can attach to them via oradebug to generate trace information.In order to identify the propagation receiver process you need to execute the query as a user with privileges to access the v$ views in both the local and remote databases so the database link must connect as a user with those privileges in the remote database. The <DBLINK> in the queries should be replaced by the appropriate database link.The queries have two forms due to the differences between operating systems. The value returned by 'Rem Process' is the operating system identifier of the propagation receiver on the remote database. Once identified, this process can be attached to and traced on the remote database using the commands given in Section 4.11.2.10.2 and below - Windows select pl.SPID "JobQ Process", pl.PROGRAM, sr.PROCESS "Rem Process" from v$PROCESS pl, DBA_JOBS_RUNNING jr, V$SESSION s, DBA_JOBS j, V$SESSION@<DBLINK> sr where s.SID=jr.SID and s.PADDR=pl.ADDR and jr.JOB=j.JOB and j.WHAT like '%sys.dbms_aqadm.aq$_propaq(job)%' and pl.SPID=substr(sr.PROCESS, instr(sr.PROCESS,':')+1); 10.2 and below - Unix select pl.SPID "JobQ Process", pl.PROGRAM, sr.PROCESS "Rem Process" from V$PROCESS pl, DBA_JOBS_RUNNING jr, V$SESSION s, DBA_JOBS j, V$SESSION@<DBLINK> sr where s.SID=jr.SID and s.PADDR=pl.ADDR and jr.JOB=j.JOB and j.WHAT like '%sys.dbms_aqadm.aq$_propaq(job)%' and pl.SPID=sr.PROCESS; 11g - Windows select pl.SPID "JobQ Process", pl.PROGRAM, sr.PROCESS "Rem Process" from V$PROCESS pl, DBA_SCHEDULER_RUNNING_JOBS jr, V$SESSION s, DBA_SCHEDULER_JOBS j, V$SESSION@<DBLINK> sr where s.SID=jr.SESSION_ID and s.PADDR=pl.ADDR and jr.JOB_NAME=j.JOB_NAME and j.JOB_NAME like '%AQ_JOB$_%%' and pl.SPID=substr(sr.PROCESS, instr(sr.PROCESS,':')+1); 11g - Unix select pl.SPID "JobQ Process", pl.PROGRAM, sr.PROCESS "Rem Process" from V$PROCESS pl, DBA_SCHEDULER_RUNNING_JOBS jr, V$SESSION s, DBA_SCHEDULER_JOBS j, V$SESSION@<DBLINK> sr where s.SID=jr.SESSION_ID and s.PADDR=pl.ADDR and jr.JOB_NAME=j.JOB_NAME and j.JOB_NAME like '%AQ_JOB$_%%' and pl.SPID=sr.PROCESS;   5. Additional Troubleshooting Steps for AQ Propagation of User-Enqueued and Dequeued Messages 5.1. Check the Privileges of All Users Involved Ensure that the owner of the database link has the necessary privileges on the aq packages. SQL> select TABLE_NAME, PRIVILEGE from USER_TAB_PRIVS;TABLE_NAME PRIVILEGE------------------------------ ----------------------------------------DBMS_LOCK EXECUTEDBMS_AQ EXECUTEDBMS_AQADM EXECUTEDBMS_AQ_BQVIEW EXECUTEQT52814_BUFFER SELECT Note that when queue table is created, a view called QT<nnn>_BUFFER is created in the SYS schema, and the queue table owner is given SELECT privileges on it. The <nnn> corresponds to the object_id of the associated queue table. SQL> select * from USER_ROLE_PRIVS;USERNAME GRANTED_ROLE ADM DEF OS_------------------------------ ------------------------------ ---- ---- ---AQ_USER1 AQ_ADMINISTRATOR_ROLE NO YES NOAQ_USER1 CONNECT NO YES NOAQ_USER1 RESOURCE NO YES NO It is good practice to configure central AQ administrative user. All admin and processing jobs are created, executed and administered as this user. This configuration is not mandatory however, and the database link can be owned by any existing queue user. If this latter configuration is used, ensure that the connecting user has the necessary privileges on the AQ packages and objects involved. Privileges for an AQ Administrative user Execute on DBMS_AQADM Execute on DBMS_AQ Granted the AQ_ADMINISTRATOR_ROLE Privileges for an AQ user Execute on DBMS_AQ Execute on the message payload Enqueue privileges on the remote queue Dequeue privileges on the originating queue Privileges need to be confirmed on both sites when propagation is scheduled to remote destinations. Verify that the user ID used to login to the destination through the database link has been granted privileges to use AQ. 5.2. Verify Queue Payload Types AQ will not propagate messages from one queue to another if the payload types of the two queues are not verified to be equivalent. An AQ administrator can verify if the source and destination's payload types match by executing the DBMS_AQADM.VERIFY_QUEUE_TYPES procedure. The results of the type checking will be stored in the SYS.AQ$_MESSAGE_TYPES table. This table can be accessed using the object identifier OID of the source queue and the address database link of the destination queue, i.e. [schema.]queue_name[@destination]. Prior to Oracle 9i the payload (message type) had to be the same for all the queue tables involved in propagation. From Oracle9i onwards a transformation can be used so that payloads can be converted from one type to another. The following procedural call made on the source database can verify whether we can propagate between the source and the destination queue tables. connect aq_user1/[email protected] serverout onDECLARErc_value number;BEGINDBMS_AQADM.VERIFY_QUEUE_TYPES(src_queue_name => 'AQ_USER1.Q_1', dest_queue_name => 'AQ_USER2.Q_2',destination => 'dbl_aq_user2.es',rc => rc_value);dbms_output.put_line('rc_value code is '||rc_value);END;/ If propagation is possible then the return code value will be 1. If it is 0 then propagation is not possible and further investigation of the types and transformations used by and in conjunction with the queue tables is required. With regard to comparison of the types the following sql can be used to extract the DDL for a specific type with' %' changed appropriately on the source and target. This can then be compared for the source and target. SET LONG 20000 set pagesize 50 EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE',false); SELECT DBMS_METADATA.GET_DDL('TYPE',t.type_name) from user_types t WHERE t.type_name like '%'; EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'DEFAULT'); 5.3. Check Message State and Destination The first step in this process is to identify the queue table associated with the problem source queue. Although you schedule propagation for a specific queue, most of the meta-data associated with that queue is stored in the underlying queue table. The following statement finds the queue table for a given queue (note that this is a multiple-consumer queue table). SQL> select QUEUE_TABLE from DBA_QUEUES where NAME = 'MULTIPLEQ';QUEUE_TABLE --------------------MULTIPLEQTABLE For a small amount of messages in a multiple-consumer queue table, the following query can be run: SQL> select MSG_STATE, CONSUMER_NAME, ADDRESS from AQ$MULTIPLEQTABLE where QUEUE = 'MULTIPLEQ';MSG_STATE CONSUMER_NAME ADDRESS-------------- ----------------------- -------------READY AQUSER2 [email protected] AQUSER1READY AQUSER3 AQADM.INQ In this example we see 2 messages ready to be propagated to remote queues and 1 that is not. If the address column is blank, the message is not scheduled for propagation and can only be dequeued from the queue upon which it was enqueued. The MSG_STATE column values are discussed in Document 102330.1 Advanced Queueing MSG_STATE Values and their Interpretation. If the address column has a value, the message has been enqueued for propagation to another queue. The first row in the example includes a database link (@M2V102.ES). This demonstrates that the message should be propagated to a queue at a remote database. The third row does not include a database link so will be propagated to a queue that resides on the same database as the source queue. The consumer name is the intended recipient at the target queue. Note that we are not querying the base queue table directly; rather, we are querying a view that is available on top of every queue table, AQ$<queue_table_name>.A more realistic query in an environment where the queue table contains thousands of messages is8.0.3-compatible multiple-consumer queue table and all compatibility single-consumer queue tables select count(*), MSG_STATE, QUEUE from AQ$<queue_table_name>  group by MSG_STATE, QUEUE; 8.1.3 and 10.0-compatible queue tables select count(*), MSG_STATE, QUEUE, CONSUMER_NAME from AQ$<queue_table_name>group by MSG_STATE, QUEUE, CONSUMER_NAME; For multiple-consumer queue tables, if you did not see the expected CONSUMER_NAME , check the syntax of the enqueue code and verify the recipients are declared correctly. If a recipients list is not used on enqueue, check the subscriber list in the AQ$_<queue_table_name>_S view (note that a single-consumer queue table does not have a subscriber view. This view records all members of the default subscription list which were added using the DBMS_AQADM.ADD_SUBSCRIBER procedure and also those enqueued using a recipient list. SQL> select QUEUE, NAME, ADDRESS from AQ$MULTIPLEQTABLE_S;QUEUE NAME ADDRESS---------- ----------- -------------MULTIPLEQ AQUSER2 [email protected] AQUSER1 In this example we have 2 subscribers registered with the queue. We have a local subscriber AQUSER1, and a remote subscriber AQUSER2, on the queue INQ, owned by AQADM, at M2V102.ES. Unless overridden with a recipient list during enqueue every message enqueued to this queue will be propagated to INQ at M2V102.ES.For 8.1 style and above multiple consumer queue tables, you can also check the following information at the target: select CONSUMER_NAME, DEQ_TXN_ID, DEQ_TIME, DEQ_USER_ID, PROPAGATED_MSGID from AQ$<queue_table_name> where QUEUE = '<QUEUE_NAME>'; For 8.0 style queues, if the queue table supports multiple consumers you can obtain the same information from the history column of the queue table: select h.CONSUMER, h.TRANSACTION_ID, h.DEQ_TIME, h.DEQ_USER, h.PROPAGATED_MSGIDfrom AQ$<queue_table_name> t, table(t.history) h where t.Q_NAME = '<QUEUE_NAME>'; A non-NULL TRANSACTION_ID indicates that the message was successfully propagated. Further, the DEQ_TIME indicates the time of propagation, the DEQ_USER indicates the userid used for propagation, and the PROPAGATED_MSGID indicates the message ID of the message that was enqueued at the destination. 6. Additional Troubleshooting Steps for Propagation in an Oracle Streams Environment 6.1. Is the Propagation Enabled? For a propagation job to propagate messages, the propagation must be enabled. For Streams, a special view called DBA_PROPAGATION exists to convey information about Streams propagations. If messages are not being propagated by a propagation as expected, then the propagation might not be enabled. To query for this: SELECT p.PROPAGATION_NAME, DECODE(s.SCHEDULE_DISABLED, 'Y', 'Disabled','N', 'Enabled') SCHEDULE_DISABLED, s.PROCESS_NAME, s.FAILURES, s.LAST_ERROR_MSGFROM DBA_QUEUE_SCHEDULES s, DBA_PROPAGATION pWHERE p.DESTINATION_DBLINK = NVL(REGEXP_SUBSTR(s.DESTINATION, '[^@]+', 1, 2), s.DESTINATION) AND s.SCHEMA = p.SOURCE_QUEUE_OWNER AND s.QNAME = p.SOURCE_QUEUE_NAME AND MESSAGE_DELIVERY_MODE = 'PERSISTENT' order by PROPAGATION_NAME; At times, the propagation job may become "broken" or fail to start after an error has been encountered or after a database restart. If an error is indicated by the above query, an attempt to disable the propagation and then re-enable it can be made. In the examples below, for the propagation named STRMADMIN_PROPAGATE where the queue name is STREAMS_QUEUE owned by STRMADMIN and the destination database link is ORCL2.WORLD, the commands would be:10.2 and above exec dbms_propagation_adm.stop_propagation('STRMADMIN_PROPAGATE'); exec dbms_propagation_adm.start_propagation('STRMADMIN_PROPAGATE'); If the above does not fix the problem, stop the propagation specifying the force parameter (2nd parameter on stop_propagation) as TRUE: exec dbms_propagation_adm.stop_propagation('STRMADMIN_PROPAGATE',true); exec dbms_propagation_adm.start_propagation('STRMADMIN_PROPAGATE'); The statistics for the propagation as well as any old error messages are cleared when the force parameter is set to TRUE. Therefore if the propagation schedule is stopped with FORCE set to TRUE, and upon restart there is still an error message in DBA_PROPAGATION, then the error message is current.9.2 or 10.1 exec dbms_aqadm.disable_propagation_schedule('STRMADMIN.STREAMS_QUEUE','ORCL2.WORLD'); exec dbms.aqadm.enable_propagation_schedule('STRMADMIN.STREAMS_QUEUE','ORCL2.WORLD'); If the above does not fix the problem, perform an unschedule of propagation and then schedule_propagation: exec dbms_aqadm.unschedule_propagation('STRMADMIN.STREAMS_QUEUE','ORCL2.WORLD'); exec dbms_aqadm.schedule_propagation('STRMADMIN.STREAMS_QUEUE','ORCL2.WORLD'); Typically if the error from the first query in Section 6.1 recurs after restarting the propagation as shown above, further troubleshooting of the error is needed. 6.2. Check Propagation Rule Sets and Transformations Inspect the configuration of the rules in the rule set that is associated with the propagation process to make sure that they evaluate to TRUE as expected. If not, then the object or schema will not be propagated. Remember that when a negative rule evaluates to TRUE, the specified object or schema will not be propagated. Finally inspect any rule-based transformations that are implemented with propagation to make sure they are changing the data in the intended way.The following query shows what rule sets are assigned to a propagation: select PROPAGATION_NAME, RULE_SET_OWNER||'.'||RULE_SET_NAME "Positive Rule Set",NEGATIVE_RULE_SET_OWNER||'.'||NEGATIVE_RULE_SET_NAME "Negative Rule Set"from DBA_PROPAGATION; The next two queries list the propagation rules and their conditions. The first is for the positive rule set, the second is for the negative rule set: set long 4000select rsr.RULE_SET_OWNER||'.'||rsr.RULE_SET_NAME RULE_SET ,rsr.RULE_OWNER||'.'||rsr.RULE_NAME RULE_NAME,r.RULE_CONDITION CONDITION fromDBA_RULE_SET_RULES rsr, DBA_RULES rwhere rsr.RULE_NAME = r.RULE_NAME and rsr.RULE_OWNER = r.RULE_OWNER and RULE_SET_NAME in(select RULE_SET_NAME from DBA_PROPAGATION) order by rsr.RULE_SET_OWNER, rsr.RULE_SET_NAME;   set long 4000select c.PROPAGATION_NAME, rsr.RULE_SET_OWNER||'.'||rsr.RULE_SET_NAME RULE_SET ,rsr.RULE_OWNER||'.'||rsr.RULE_NAME RULE_NAME,r.RULE_CONDITION CONDITION fromDBA_RULE_SET_RULES rsr, DBA_RULES r ,DBA_PROPAGATION cwhere rsr.RULE_NAME = r.RULE_NAME and rsr.RULE_OWNER = r.RULE_OWNER andrsr.RULE_SET_OWNER=c.NEGATIVE_RULE_SET_OWNER and rsr.RULE_SET_NAME=c.NEGATIVE_RULE_SET_NAMEand rsr.RULE_SET_NAME in(select NEGATIVE_RULE_SET_NAME from DBA_PROPAGATION) order by rsr.RULE_SET_OWNER, rsr.RULE_SET_NAME; 6.3. Determining the Total Number of Messages and Bytes Propagated As in Section 3.1, determining if messages are flowing can be instructive to see whether the propagation is entirely hung or just slow. If the propagation is not in flow control (see Section 6.5.2), but the statistics are incrementing slowly, there may be a performance issue. For Streams implementations two views are available that can assist with this that can show the number of messages sent by a propagation, as well as the number of acknowledgements being returned from the target site: the V$PROPAGATION_SENDER view at the Source site and the V$PROPAGATION_RECEIVER view at the destination site. It is helpful to query both to determine if messages are being delivered to the target. Look for the statistics to increase.Source: select QUEUE_SCHEMA, QUEUE_NAME, DBLINK,HIGH_WATER_MARK, ACKNOWLEDGEMENT, TOTAL_MSGS, TOTAL_BYTESfrom V$PROPAGATION_SENDER; Target: select SRC_QUEUE_SCHEMA, SRC_QUEUE_NAME, SRC_DBNAME, DST_QUEUE_SCHEMA, DST_QUEUE_NAME, HIGH_WATER_MARK, ACKNOWLEDGEMENT, TOTAL_MSGS from V$PROPAGATION_RECEIVER; 6.4. Check Buffered Subscribers The V$BUFFERED_SUBSCRIBERS view displays information about subscribers for all buffered queues in the instance. This view can be queried to make sure that the site that the propagation is propagating to is listed as a subscriber address for the site being propagated from: select QUEUE_SCHEMA, QUEUE_NAME, SUBSCRIBER_ADDRESS from V$BUFFERED_SUBSCRIBERS; The SUBSCRIBER_ADDRESS column will not be populated when the propagation is local (between queues on the same database). 6.5. Common Streams Propagation Errors 6.5.1. ORA-02082: A loopback database link must have a connection qualifier. This error can occur if you use the Streams Setup Wizard in Oracle Enterprise Manager without first configuring the GLOBAL_NAME for your database. 6.5.2. ORA-25307: Enqueue rate too high. Enable flow control DBA_QUEUE_SCHEDULES will display this informational message for propagation when the automatic flow control (10g feature of Streams) has been invoked.Similar to Streams capture processes, a Streams propagation process can also go into a state of 'flow control. This is an informative message that indicates flow control has been automatically enabled to reduce the rate at which messages are being enqueued into at target queue.This typically occurs when the target site is unable to keep up with the rate of messages flowing from the source site. Other than checking that the apply process is running normally on the target site, usually no action is required by the DBA. Propagation and the capture process will be resumed automatically when the target site is able to accept more messages.The following document contains more information:Document 302109.1 Streams Propagation Error: ORA-25307 Enqueue rate too high. Enable flow controlSee the following document for one potential cause of this situation:Document 1097115.1 Oracle Streams Apply Reader is in 'Paused' State 6.5.3. ORA-25315 unsupported configuration for propagation of buffered messages This error typically occurs when the target database is RAC and usually indicates that an attempt was made to propagate buffered messages with the database link pointing to an instance in the destination database which is not the owner instance of the destination queue. To resolve the problem, use queue-to-queue propagation for buffered messages. 6.5.4. ORA-600 [KWQBMCRCPTS101] after dropping / recreating propagation For cause/fixes refer to:Document 421237.1 ORA-600 [KWQBMCRCPTS101] reported by a Qmon slave process after dropping a Streams Propagation 6.5.5. Stopping or Dropping a Streams Propagation Hangs See the following note:Document 1159787.1 Troubleshooting Streams Propagation When It is Not Functioning and Attempts to Stop It Hang 6.6. Streams Propagation-Related Notes for Common Issues Document 437838.1 Streams Specific PatchesDocument 749181.1 How to Recover Streams After Dropping PropagationDocument 368912.1 Queue to Queue Propagation Schedule encountered ORA-12514 in a RAC environmentDocument 564649.1 ORA-02068/ORA-03114/ORA-03113 Errors From Streams Propagation Process - Remote Database is Available and Unschedule/Reschedule Does Not ResolveDocument 553017.1 Stream Propagation Process Errors Ora-4052 Ora-6554 From 11g To 10201Document 944846.1 Streams Propagation Fails Ora-7445 [kohrsmc]Document 745601.1 ORA-23603 'STREAMS enqueue aborted due to low SGA' Error from Streams Propagation, and V$STREAMS_CAPTURE.STATE Hanging on 'Enqueuing Message'Document 333068.1 ORA-23603: Streams Enqueue Aborted Eue To Low SGADocument 363496.1 Ora-25315 Propagating on RAC StreamsDocument 368237.1 Unable to Unschedule Propagation. Streams Queue is InvalidDocument 436332.1 dbms_propagation_adm.stop_propagation hangsDocument 727389.1 Propagation Fails With ORA-12528Document 730911.1 ORA-4063 Is Reported After Dropping Negative Prop.RulesetDocument 460471.1 Propagation Blocked by Qmon Process - Streams_queue_table / 'library cache lock' waitsDocument 1165583.1 ORA-600 [kwqpuspse0-ack] In Streams EnvironmentDocument 1059029.1 Combined Capture and Apply (CCA) : Capture aborts : ORA-1422 after schedule_propagationDocument 556309.1 Changing Propagation/ queue_to_queue : false -> true does does not work; no LCRs propagatedDocument 839568.1 Propagation failing with error: ORA-01536: space quota exceeded for tablespace ''Document 311021.1 Streams Propagation Process : Ora 12154 After Reboot with Transparent Application Failover TAF configuredDocument 359971.1 STREAMS propagation to Primary of physical Standby configuation errors with Ora-01033, Ora-02068Document 1101616.1 DBMS_PROPAGATION_ADM.DROP_PROPAGATION FAILS WITH ORA-1747 7. Performance Issues A propagation may seem to be slow if the queries from Sections 3.1 and 6.3 show that the message statistics are not changing quickly. In Oracle Streams, this more usually is due to a slow apply process at the target rather than a slow propagation. Propagation could be inferred to be slow if the message statistics are changing, and the state of a capture process according to V$STREAMS_CAPTURE.STATE is PAUSED FOR FLOW CONTROL, but an ORA-25307 'Enqueue rate too high. Enable flow control' warning is NOT observed in DBA_QUEUE_SCHEDULES per Section 6.5.2. If this is the case, see the following notes / white papers for suggestions to increase performance:Document 335516.1 Master Note for Streams Performance RecommendationsDocument 730036.1 Overview for Troubleshooting Streams Performance IssuesDocument 780733.1 Streams Propagation Tuning with Network ParametersWhite Paper: http://www.oracle.com/technetwork/database/features/availability/maa-wp-10gr2-streams-performance-130059.pdfWhite Paper: Oracle Streams Configuration Best Practices: Oracle Database 10g Release 10.2, http://www.oracle.com/technetwork/database/features/availability/maa-10gr2-streams-configuration-132039.pdf, See APPENDIX A: USING STREAMS CONFIGURATIONS OVER A NETWORKFor basic AQ propagation, the network tuning in the aforementioned Appendix A of the white paper 'Oracle Streams Configuration Best Practices: Oracle Database 10g Release 10.2' is applicable. References NOTE:102330.1 - Advanced Queueing MSG_STATE Values and their InterpretationNOTE:102771.1 - Advanced Queueing Propagation using PL/SQLNOTE:1059029.1 - Combined Capture and Apply (CCA) : Capture aborts : ORA-1422 after schedule_propagationNOTE:1079577.1 - Advanced Queuing Propagation Fails With "ORA-22370: incorrect usage of method"NOTE:1083608.1 - 11g Streams and Oracle SchedulerNOTE:1087324.1 - ORA-01405 ORA-01422 reported by Adavanced Queueing Propagation schedules after RAC reconfigurationNOTE:1097115.1 - Oracle Streams Apply Reader is in 'Paused' StateNOTE:1101616.1 - DBMS_PROPAGATION_ADM.DROP_PROPAGATION FAILS WITH ORA-1747NOTE:1159787.1 - Troubleshooting Streams Propagation When It is Not Functioning and Attempts to Stop It HangNOTE:1165583.1 - ORA-600 [kwqpuspse0-ack] In Streams EnvironmentNOTE:118884.1 - How to unschedule a propagation schedule stuck in pending stateNOTE:1203544.1 - AQ PROPAGATION ABORTED WITH ORA-600[OCIKSIN: INVALID STATUS] ON SYS.DBMS_AQADM_SYS.AQ$_PROPAGATION_PROCEDURE AFTER UPGRADENOTE:1204080.1 - AQ Propagation Failing With ORA-25329 After Upgraded From 8i or 9i to 10g or 11g.NOTE:219416.1 - Advanced Queuing Propagation fails with ORA-22922NOTE:222992.1 - DBMS_AQADM.DISABLE_PROPAGATION_SCHEDULE Returns ORA-24082NOTE:253131.1 - Concurrent Writes May Corrupt LOB Segment When Using Auto Segment Space Management (ORA-1555)NOTE:282987.1 - Propagated Messages marked UNDELIVERABLE after Drop and Recreate Of Remote QueueNOTE:298015.1 - Kwqjswproc:Excep After Loop: Assigning To SelfNOTE:302109.1 - Streams Propagation Error: ORA-25307 Enqueue rate too high. Enable flow controlNOTE:311021.1 - Streams Propagation Process : Ora 12154 After Reboot with Transparent Application Failover TAF configuredNOTE:332792.1 - ORA-04061 error relating to SYS.DBMS_PRVTAQIP reported when setting up StatspackNOTE:333068.1 - ORA-23603: Streams Enqueue Aborted Eue To Low SGANOTE:335516.1 - Master Note for Streams Performance RecommendationsNOTE:353325.1 - ORA-24056: Internal inconsistency for QUEUE and destination NOTE:353754.1 - Streams Messaging Propagation Fails between Single and Multi-byte Charactersets when using Chararacter Length Semantics in the ADT.NOTE:359971.1 - STREAMS propagation to Primary of physical Standby configuation errors with Ora-01033, Ora-02068NOTE:363496.1 - Ora-25315 Propagating on RAC StreamsNOTE:365093.1 - ORA-07445 [kwqppay2aqe()+7360] reported on Propagation of a Transformed MessageNOTE:368237.1 - Unable to Unschedule Propagation. Streams Queue is InvalidNOTE:368912.1 - Queue to Queue Propagation Schedule encountered ORA-12514 in a RAC environmentNOTE:421237.1 - ORA-600 [KWQBMCRCPTS101] reported by a Qmon slave process after dropping a Streams PropagationNOTE:436332.1 - dbms_propagation_adm.stop_propagation hangsNOTE:437838.1 - Streams Specific PatchesNOTE:460471.1 - Propagation Blocked by Qmon Process - Streams_queue_table / 'library cache lock' waitsNOTE:463820.1 - Streams Combined Capture and Apply in 11gNOTE:553017.1 - Stream Propagation Process Errors Ora-4052 Ora-6554 From 11g To 10201NOTE:556309.1 - Changing Propagation/ queue_to_queue : false -> true does does not work; no LCRs propagatedNOTE:564649.1 - ORA-02068/ORA-03114/ORA-03113 Errors From Streams Propagation Process - Remote Database is Available and Unschedule/Reschedule Does Not ResolveNOTE:566622.1 - ORA-22275 when propagating >4K AQ$_JMS_TEXT_MESSAGEs from 9.2.0.8 to 10.2.0.1NOTE:727389.1 - Propagation Fails With ORA-12528NOTE:730036.1 - Overview for Troubleshooting Streams Performance IssuesNOTE:730911.1 - ORA-4063 Is Reported After Dropping Negative Prop.RulesetNOTE:731292.1 - ORA-25215 Reported On Local Propagation When Using Transformation with ANYDATA queue tablesNOTE:731539.1 - ORA-29268: HTTP client error 401 Unauthorized Error when the AQ Servlet attempts to Propagate a message via HTTPNOTE:745601.1 - ORA-23603 'STREAMS enqueue aborted due to low SGA' Error from Streams Propagation, and V$STREAMS_CAPTURE.STATE Hanging on 'Enqueuing Message'NOTE:749181.1 - How to Recover Streams After Dropping PropagationNOTE:780733.1 - Streams Propagation Tuning with Network ParametersNOTE:787367.1 - ORA-22275 reported on Propagating Messages with LOB component when propagating between 10.1 and 10.2NOTE:808136.1 - How to clear the old errors from DBA_PROPAGATION view ?NOTE:827184.1 - AQ Propagation with CLOB data types Fails with ORA-22990NOTE:827473.1 - How to alter propagation from queue_to_queue to queue_to_dblinkNOTE:839568.1 - Propagation failing with error: ORA-01536: space quota exceeded for tablespace ''NOTE:846297.1 - AQ Propagation Fails : ORA-00600[kope2upic2954] or Ora-00600[Kghsstream_copyn]NOTE:944846.1 - Streams Propagation Fails Ora-7445 [kohrsmc]

    Read the article

  • The Incremental Architect&rsquo;s Napkin - #5 - Design functions for extensibility and readability

    - by Ralf Westphal
    Originally posted on: http://geekswithblogs.net/theArchitectsNapkin/archive/2014/08/24/the-incremental-architectrsquos-napkin---5---design-functions-for.aspx The functionality of programs is entered via Entry Points. So what we´re talking about when designing software is a bunch of functions handling the requests represented by and flowing in through those Entry Points. Designing software thus consists of at least three phases: Analyzing the requirements to find the Entry Points and their signatures Designing the functionality to be executed when those Entry Points get triggered Implementing the functionality according to the design aka coding I presume, you´re familiar with phase 1 in some way. And I guess you´re proficient in implementing functionality in some programming language. But in my experience developers in general are not experienced in going through an explicit phase 2. “Designing functionality? What´s that supposed to mean?” you might already have thought. Here´s my definition: To design functionality (or functional design for short) means thinking about… well, functions. You find a solution for what´s supposed to happen when an Entry Point gets triggered in terms of functions. A conceptual solution that is, because those functions only exist in your head (or on paper) during this phase. But you may have guess that, because it´s “design” not “coding”. And here is, what functional design is not: It´s not about logic. Logic is expressions (e.g. +, -, && etc.) and control statements (e.g. if, switch, for, while etc.). Also I consider calling external APIs as logic. It´s equally basic. It´s what code needs to do in order to deliver some functionality or quality. Logic is what´s doing that needs to be done by software. Transformations are either done through expressions or API-calls. And then there is alternative control flow depending on the result of some expression. Basically it´s just jumps in Assembler, sometimes to go forward (if, switch), sometimes to go backward (for, while, do). But calling your own function is not logic. It´s not necessary to produce any outcome. Functionality is not enhanced by adding functions (subroutine calls) to your code. Nor is quality increased by adding functions. No performance gain, no higher scalability etc. through functions. Functions are not relevant to functionality. Strange, isn´t it. What they are important for is security of investment. By introducing functions into our code we can become more productive (re-use) and can increase evolvability (higher unterstandability, easier to keep code consistent). That´s no small feat, however. Evolvable code can hardly be overestimated. That´s why to me functional design is so important. It´s at the core of software development. To sum this up: Functional design is on a level of abstraction above (!) logical design or algorithmic design. Functional design is only done until you get to a point where each function is so simple you are very confident you can easily code it. Functional design an logical design (which mostly is coding, but can also be done using pseudo code or flow charts) are complementary. Software needs both. If you start coding right away you end up in a tangled mess very quickly. Then you need back out through refactoring. Functional design on the other hand is bloodless without actual code. It´s just a theory with no experiments to prove it. But how to do functional design? An example of functional design Let´s assume a program to de-duplicate strings. The user enters a number of strings separated by commas, e.g. a, b, a, c, d, b, e, c, a. And the program is supposed to clear this list of all doubles, e.g. a, b, c, d, e. There is only one Entry Point to this program: the user triggers the de-duplication by starting the program with the string list on the command line C:\>deduplicate "a, b, a, c, d, b, e, c, a" a, b, c, d, e …or by clicking on a GUI button. This leads to the Entry Point function to get called. It´s the program´s main function in case of the batch version or a button click event handler in the GUI version. That´s the physical Entry Point so to speak. It´s inevitable. What then happens is a three step process: Transform the input data from the user into a request. Call the request handler. Transform the output of the request handler into a tangible result for the user. Or to phrase it a bit more generally: Accept input. Transform input into output. Present output. This does not mean any of these steps requires a lot of effort. Maybe it´s just one line of code to accomplish it. Nevertheless it´s a distinct step in doing the processing behind an Entry Point. Call it an aspect or a responsibility - and you will realize it most likely deserves a function of its own to satisfy the Single Responsibility Principle (SRP). Interestingly the above list of steps is already functional design. There is no logic, but nevertheless the solution is described - albeit on a higher level of abstraction than you might have done yourself. But it´s still on a meta-level. The application to the domain at hand is easy, though: Accept string list from command line De-duplicate Present de-duplicated strings on standard output And this concrete list of processing steps can easily be transformed into code:static void Main(string[] args) { var input = Accept_string_list(args); var output = Deduplicate(input); Present_deduplicated_string_list(output); } Instead of a big problem there are three much smaller problems now. If you think each of those is trivial to implement, then go for it. You can stop the functional design at this point. But maybe, just maybe, you´re not so sure how to go about with the de-duplication for example. Then just implement what´s easy right now, e.g.private static string Accept_string_list(string[] args) { return args[0]; } private static void Present_deduplicated_string_list( string[] output) { var line = string.Join(", ", output); Console.WriteLine(line); } Accept_string_list() contains logic in the form of an API-call. Present_deduplicated_string_list() contains logic in the form of an expression and an API-call. And then repeat the functional design for the remaining processing step. What´s left is the domain logic: de-duplicating a list of strings. How should that be done? Without any logic at our disposal during functional design you´re left with just functions. So which functions could make up the de-duplication? Here´s a suggestion: De-duplicate Parse the input string into a true list of strings. Register each string in a dictionary/map/set. That way duplicates get cast away. Transform the data structure into a list of unique strings. Processing step 2 obviously was the core of the solution. That´s where real creativity was needed. That´s the core of the domain. But now after this refinement the implementation of each step is easy again:private static string[] Parse_string_list(string input) { return input.Split(',') .Select(s => s.Trim()) .ToArray(); } private static Dictionary<string,object> Compile_unique_strings(string[] strings) { return strings.Aggregate( new Dictionary<string, object>(), (agg, s) => { agg[s] = null; return agg; }); } private static string[] Serialize_unique_strings( Dictionary<string,object> dict) { return dict.Keys.ToArray(); } With these three additional functions Main() now looks like this:static void Main(string[] args) { var input = Accept_string_list(args); var strings = Parse_string_list(input); var dict = Compile_unique_strings(strings); var output = Serialize_unique_strings(dict); Present_deduplicated_string_list(output); } I think that´s very understandable code: just read it from top to bottom and you know how the solution to the problem works. It´s a mirror image of the initial design: Accept string list from command line Parse the input string into a true list of strings. Register each string in a dictionary/map/set. That way duplicates get cast away. Transform the data structure into a list of unique strings. Present de-duplicated strings on standard output You can even re-generate the design by just looking at the code. Code and functional design thus are always in sync - if you follow some simple rules. But about that later. And as a bonus: all the functions making up the process are small - which means easy to understand, too. So much for an initial concrete example. Now it´s time for some theory. Because there is method to this madness ;-) The above has only scratched the surface. Introducing Flow Design Functional design starts with a given function, the Entry Point. Its goal is to describe the behavior of the program when the Entry Point is triggered using a process, not an algorithm. An algorithm consists of logic, a process on the other hand consists just of steps or stages. Each processing step transforms input into output or a side effect. Also it might access resources, e.g. a printer, a database, or just memory. Processing steps thus can rely on state of some sort. This is different from Functional Programming, where functions are supposed to not be stateful and not cause side effects.[1] In its simplest form a process can be written as a bullet point list of steps, e.g. Get data from user Output result to user Transform data Parse data Map result for output Such a compilation of steps - possibly on different levels of abstraction - often is the first artifact of functional design. It can be generated by a team in an initial design brainstorming. Next comes ordering the steps. What should happen first, what next etc.? Get data from user Parse data Transform data Map result for output Output result to user That´s great for a start into functional design. It´s better than starting to code right away on a given function using TDD. Please get me right: TDD is a valuable practice. But it can be unnecessarily hard if the scope of a functionn is too large. But how do you know beforehand without investing some thinking? And how to do this thinking in a systematic fashion? My recommendation: For any given function you´re supposed to implement first do a functional design. Then, once you´re confident you know the processing steps - which are pretty small - refine and code them using TDD. You´ll see that´s much, much easier - and leads to cleaner code right away. For more information on this approach I call “Informed TDD” read my book of the same title. Thinking before coding is smart. And writing down the solution as a bunch of functions possibly is the simplest thing you can do, I´d say. It´s more according to the KISS (Keep It Simple, Stupid) principle than returning constants or other trivial stuff TDD development often is started with. So far so good. A simple ordered list of processing steps will do to start with functional design. As shown in the above example such steps can easily be translated into functions. Moving from design to coding thus is simple. However, such a list does not scale. Processing is not always that simple to be captured in a list. And then the list is just text. Again. Like code. That means the design is lacking visuality. Textual representations need more parsing by your brain than visual representations. Plus they are limited in their “dimensionality”: text just has one dimension, it´s sequential. Alternatives and parallelism are hard to encode in text. In addition the functional design using numbered lists lacks data. It´s not visible what´s the input, output, and state of the processing steps. That´s why functional design should be done using a lightweight visual notation. No tool is necessary to draw such designs. Use pen and paper; a flipchart, a whiteboard, or even a napkin is sufficient. Visualizing processes The building block of the functional design notation is a functional unit. I mostly draw it like this: Something is done, it´s clear what goes in, it´s clear what comes out, and it´s clear what the processing step requires in terms of state or hardware. Whenever input flows into a functional unit it gets processed and output is produced and/or a side effect occurs. Flowing data is the driver of something happening. That´s why I call this approach to functional design Flow Design. It´s about data flow instead of control flow. Control flow like in algorithms is of no concern to functional design. Thinking about control flow simply is too low level. Once you start with control flow you easily get bogged down by tons of details. That´s what you want to avoid during design. Design is supposed to be quick, broad brush, abstract. It should give overview. But what about all the details? As Robert C. Martin rightly said: “Programming is abot detail”. Detail is a matter of code. Once you start coding the processing steps you designed you can worry about all the detail you want. Functional design does not eliminate all the nitty gritty. It just postpones tackling them. To me that´s also an example of the SRP. Function design has the responsibility to come up with a solution to a problem posed by a single function (Entry Point). And later coding has the responsibility to implement the solution down to the last detail (i.e. statement, API-call). TDD unfortunately mixes both responsibilities. It´s just coding - and thereby trying to find detailed implementations (green phase) plus getting the design right (refactoring). To me that´s one reason why TDD has failed to deliver on its promise for many developers. Using functional units as building blocks of functional design processes can be depicted very easily. Here´s the initial process for the example problem: For each processing step draw a functional unit and label it. Choose a verb or an “action phrase” as a label, not a noun. Functional design is about activities, not state or structure. Then make the output of an upstream step the input of a downstream step. Finally think about the data that should flow between the functional units. Write the data above the arrows connecting the functional units in the direction of the data flow. Enclose the data description in brackets. That way you can clearly see if all flows have already been specified. Empty brackets mean “no data is flowing”, but nevertheless a signal is sent. A name like “list” or “strings” in brackets describes the data content. Use lower case labels for that purpose. A name starting with an upper case letter like “String” or “Customer” on the other hand signifies a data type. If you like, you also can combine descriptions with data types by separating them with a colon, e.g. (list:string) or (strings:string[]). But these are just suggestions from my practice with Flow Design. You can do it differently, if you like. Just be sure to be consistent. Flows wired-up in this manner I call one-dimensional (1D). Each functional unit just has one input and/or one output. A functional unit without an output is possible. It´s like a black hole sucking up input without producing any output. Instead it produces side effects. A functional unit without an input, though, does make much sense. When should it start to work? What´s the trigger? That´s why in the above process even the first processing step has an input. If you like, view such 1D-flows as pipelines. Data is flowing through them from left to right. But as you can see, it´s not always the same data. It get´s transformed along its passage: (args) becomes a (list) which is turned into (strings). The Principle of Mutual Oblivion A very characteristic trait of flows put together from function units is: no functional units knows another one. They are all completely independent of each other. Functional units don´t know where their input is coming from (or even when it´s gonna arrive). They just specify a range of values they can process. And they promise a certain behavior upon input arriving. Also they don´t know where their output is going. They just produce it in their own time independent of other functional units. That means at least conceptually all functional units work in parallel. Functional units don´t know their “deployment context”. They now nothing about the overall flow they are place in. They are just consuming input from some upstream, and producing output for some downstream. That makes functional units very easy to test. At least as long as they don´t depend on state or resources. I call this the Principle of Mutual Oblivion (PoMO). Functional units are oblivious of others as well as an overall context/purpose. They are just parts of a whole focused on a single responsibility. How the whole is built, how a larger goal is achieved, is of no concern to the single functional units. By building software in such a manner, functional design interestingly follows nature. Nature´s building blocks for organisms also follow the PoMO. The cells forming your body do not know each other. Take a nerve cell “controlling” a muscle cell for example:[2] The nerve cell does not know anything about muscle cells, let alone the specific muscel cell it is “attached to”. Likewise the muscle cell does not know anything about nerve cells, let a lone a specific nerve cell “attached to” it. Saying “the nerve cell is controlling the muscle cell” thus only makes sense when viewing both from the outside. “Control” is a concept of the whole, not of its parts. Control is created by wiring-up parts in a certain way. Both cells are mutually oblivious. Both just follow a contract. One produces Acetylcholine (ACh) as output, the other consumes ACh as input. Where the ACh is going, where it´s coming from neither cell cares about. Million years of evolution have led to this kind of division of labor. And million years of evolution have produced organism designs (DNA) which lead to the production of these different cell types (and many others) and also to their co-location. The result: the overall behavior of an organism. How and why this happened in nature is a mystery. For our software, though, it´s clear: functional and quality requirements needs to be fulfilled. So we as developers have to become “intelligent designers” of “software cells” which we put together to form a “software organism” which responds in satisfying ways to triggers from it´s environment. My bet is: If nature gets complex organisms working by following the PoMO, who are we to not apply this recipe for success to our much simpler “machines”? So my rule is: Wherever there is functionality to be delivered, because there is a clear Entry Point into software, design the functionality like nature would do it. Build it from mutually oblivious functional units. That´s what Flow Design is about. In that way it´s even universal, I´d say. Its notation can also be applied to biology: Never mind labeling the functional units with nouns. That´s ok in Flow Design. You´ll do that occassionally for functional units on a higher level of abstraction or when their purpose is close to hardware. Getting a cockroach to roam your bedroom takes 1,000,000 nerve cells (neurons). Getting the de-duplication program to do its job just takes 5 “software cells” (functional units). Both, though, follow the same basic principle. Translating functional units into code Moving from functional design to code is no rocket science. In fact it´s straightforward. There are two simple rules: Translate an input port to a function. Translate an output port either to a return statement in that function or to a function pointer visible to that function. The simplest translation of a functional unit is a function. That´s what you saw in the above example. Functions are mutually oblivious. That why Functional Programming likes them so much. It makes them composable. Which is the reason, nature works according to the PoMO. Let´s be clear about one thing: There is no dependency injection in nature. For all of an organism´s complexity no DI container is used. Behavior is the result of smooth cooperation between mutually oblivious building blocks. Functions will often be the adequate translation for the functional units in your designs. But not always. Take for example the case, where a processing step should not always produce an output. Maybe the purpose is to filter input. Here the functional unit consumes words and produces words. But it does not pass along every word flowing in. Some words are swallowed. Think of a spell checker. It probably should not check acronyms for correctness. There are too many of them. Or words with no more than two letters. Such words are called “stop words”. In the above picture the optionality of the output is signified by the astrisk outside the brackets. It means: Any number of (word) data items can flow from the functional unit for each input data item. It might be none or one or even more. This I call a stream of data. Such behavior cannot be translated into a function where output is generated with return. Because a function always needs to return a value. So the output port is translated into a function pointer or continuation which gets passed to the subroutine when called:[3]void filter_stop_words( string word, Action<string> onNoStopWord) { if (...check if not a stop word...) onNoStopWord(word); } If you want to be nitpicky you might call such a function pointer parameter an injection. And technically you´re right. Conceptually, though, it´s not an injection. Because the subroutine is not functionally dependent on the continuation. Firstly continuations are procedures, i.e. subroutines without a return type. Remember: Flow Design is about unidirectional data flow. Secondly the name of the formal parameter is chosen in a way as to not assume anything about downstream processing steps. onNoStopWord describes a situation (or event) within the functional unit only. Translating output ports into function pointers helps keeping functional units mutually oblivious in cases where output is optional or produced asynchronically. Either pass the function pointer to the function upon call. Or make it global by putting it on the encompassing class. Then it´s called an event. In C# that´s even an explicit feature.class Filter { public void filter_stop_words( string word) { if (...check if not a stop word...) onNoStopWord(word); } public event Action<string> onNoStopWord; } When to use a continuation and when to use an event dependens on how a functional unit is used in flows and how it´s packed together with others into classes. You´ll see examples further down the Flow Design road. Another example of 1D functional design Let´s see Flow Design once more in action using the visual notation. How about the famous word wrap kata? Robert C. Martin has posted a much cited solution including an extensive reasoning behind his TDD approach. So maybe you want to compare it to Flow Design. The function signature given is:string WordWrap(string text, int maxLineLength) {...} That´s not an Entry Point since we don´t see an application with an environment and users. Nevertheless it´s a function which is supposed to provide a certain functionality. The text passed in has to be reformatted. The input is a single line of arbitrary length consisting of words separated by spaces. The output should consist of one or more lines of a maximum length specified. If a word is longer than a the maximum line length it can be split in multiple parts each fitting in a line. Flow Design Let´s start by brainstorming the process to accomplish the feat of reformatting the text. What´s needed? Words need to be assembled into lines Words need to be extracted from the input text The resulting lines need to be assembled into the output text Words too long to fit in a line need to be split Does sound about right? I guess so. And it shows a kind of priority. Long words are a special case. So maybe there is a hint for an incremental design here. First let´s tackle “average words” (words not longer than a line). Here´s the Flow Design for this increment: The the first three bullet points turned into functional units with explicit data added. As the signature requires a text is transformed into another text. See the input of the first functional unit and the output of the last functional unit. In between no text flows, but words and lines. That´s good to see because thereby the domain is clearly represented in the design. The requirements are talking about words and lines and here they are. But note the asterisk! It´s not outside the brackets but inside. That means it´s not a stream of words or lines, but lists or sequences. For each text a sequence of words is output. For each sequence of words a sequence of lines is produced. The asterisk is used to abstract from the concrete implementation. Like with streams. Whether the list of words gets implemented as an array or an IEnumerable is not important during design. It´s an implementation detail. Does any processing step require further refinement? I don´t think so. They all look pretty “atomic” to me. And if not… I can always backtrack and refine a process step using functional design later once I´ve gained more insight into a sub-problem. Implementation The implementation is straightforward as you can imagine. The processing steps can all be translated into functions. Each can be tested easily and separately. Each has a focused responsibility. And the process flow becomes just a sequence of function calls: Easy to understand. It clearly states how word wrapping works - on a high level of abstraction. And it´s easy to evolve as you´ll see. Flow Design - Increment 2 So far only texts consisting of “average words” are wrapped correctly. Words not fitting in a line will result in lines too long. Wrapping long words is a feature of the requested functionality. Whether it´s there or not makes a difference to the user. To quickly get feedback I decided to first implement a solution without this feature. But now it´s time to add it to deliver the full scope. Fortunately Flow Design automatically leads to code following the Open Closed Principle (OCP). It´s easy to extend it - instead of changing well tested code. How´s that possible? Flow Design allows for extension of functionality by inserting functional units into the flow. That way existing functional units need not be changed. The data flow arrow between functional units is a natural extension point. No need to resort to the Strategy Pattern. No need to think ahead where extions might need to be made in the future. I just “phase in” the remaining processing step: Since neither Extract words nor Reformat know of their environment neither needs to be touched due to the “detour”. The new processing step accepts the output of the existing upstream step and produces data compatible with the existing downstream step. Implementation - Increment 2 A trivial implementation checking the assumption if this works does not do anything to split long words. The input is just passed on: Note how clean WordWrap() stays. The solution is easy to understand. A developer looking at this code sometime in the future, when a new feature needs to be build in, quickly sees how long words are dealt with. Compare this to Robert C. Martin´s solution:[4] How does this solution handle long words? Long words are not even part of the domain language present in the code. At least I need considerable time to understand the approach. Admittedly the Flow Design solution with the full implementation of long word splitting is longer than Robert C. Martin´s. At least it seems. Because his solution does not cover all the “word wrap situations” the Flow Design solution handles. Some lines would need to be added to be on par, I guess. But even then… Is a difference in LOC that important as long as it´s in the same ball park? I value understandability and openness for extension higher than saving on the last line of code. Simplicity is not just less code, it´s also clarity in design. But don´t take my word for it. Try Flow Design on larger problems and compare for yourself. What´s the easier, more straightforward way to clean code? And keep in mind: You ain´t seen all yet ;-) There´s more to Flow Design than described in this chapter. In closing I hope I was able to give you a impression of functional design that makes you hungry for more. To me it´s an inevitable step in software development. Jumping from requirements to code does not scale. And it leads to dirty code all to quickly. Some thought should be invested first. Where there is a clear Entry Point visible, it´s functionality should be designed using data flows. Because with data flows abstraction is possible. For more background on why that´s necessary read my blog article here. For now let me point out to you - if you haven´t already noticed - that Flow Design is a general purpose declarative language. It´s “programming by intention” (Shalloway et al.). Just write down how you think the solution should work on a high level of abstraction. This breaks down a large problem in smaller problems. And by following the PoMO the solutions to those smaller problems are independent of each other. So they are easy to test. Or you could even think about getting them implemented in parallel by different team members. Flow Design not only increases evolvability, but also helps becoming more productive. All team members can participate in functional design. This goes beyon collective code ownership. We´re talking collective design/architecture ownership. Because with Flow Design there is a common visual language to talk about functional design - which is the foundation for all other design activities.   PS: If you like what you read, consider getting my ebook “The Incremental Architekt´s Napkin”. It´s where I compile all the articles in this series for easier reading. I like the strictness of Function Programming - but I also find it quite hard to live by. And it certainly is not what millions of programmers are used to. Also to me it seems, the real world is full of state and side effects. So why give them such a bad image? That´s why functional design takes a more pragmatic approach. State and side effects are ok for processing steps - but be sure to follow the SRP. Don´t put too much of it into a single processing step. ? Image taken from www.physioweb.org ? My code samples are written in C#. C# sports typed function pointers called delegates. Action is such a function pointer type matching functions with signature void someName(T t). Other languages provide similar ways to work with functions as first class citizens - even Java now in version 8. I trust you find a way to map this detail of my translation to your favorite programming language. I know it works for Java, C++, Ruby, JavaScript, Python, Go. And if you´re using a Functional Programming language it´s of course a no brainer. ? Taken from his blog post “The Craftsman 62, The Dark Path”. ?

    Read the article

  • MySQL Syslog Audit Plugin

    - by jonathonc
    This post shows the construction process of the Syslog Audit plugin that was presented at MySQL Connect 2012. It is based on an environment that has the appropriate development tools enabled including gcc,g++ and cmake. It also assumes you have downloaded the MySQL source code (5.5.16 or higher) and have compiled and installed the system into the /usr/local/mysql directory ready for use.  The information provided below is designed to show the different components that make up a plugin, and specifically an audit type plugin, and how it comes together to be used within the MySQL service. The MySQL Reference Manual contains information regarding the plugin API and how it can be used, so please refer there for more detailed information. The code in this post is designed to give the simplest information necessary, so handling every return code, managing race conditions etc is not part of this example code. Let's start by looking at the most basic implementation of our plugin code as seen below: /*    Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.    Author:  Jonathon Coombes    Licence: GPL    Description: An auditing plugin that logs to syslog and                 can adjust the loglevel via the system variables. */ #include <stdio.h> #include <string.h> #include <mysql/plugin_audit.h> #include <syslog.h> There is a commented header detailing copyright/licencing and meta-data information and then the include headers. The two important include statements for our plugin are the syslog.h plugin, which gives us the structures for syslog, and the plugin_audit.h include which has details regarding the audit specific plugin api. Note that we do not need to include the general plugin header plugin.h, as this is done within the plugin_audit.h file already. To implement our plugin within the current implementation we need to add it into our source code and compile. > cd /usr/local/src/mysql-5.5.28/plugin > mkdir audit_syslog > cd audit_syslog A simple CMakeLists.txt file is created to manage the plugin compilation: MYSQL_ADD_PLUGIN(audit_syslog audit_syslog.cc MODULE_ONLY) Run the cmake  command at the top level of the source and then you can compile the plugin using the 'make' command. This results in a compiled audit_syslog.so library, but currently it is not much use to MySQL as there is no level of api defined to communicate with the MySQL service. Now we need to define the general plugin structure that enables MySQL to recognise the library as a plugin and be able to install/uninstall it and have it show up in the system. The structure is defined in the plugin.h file in the MySQL source code.  /*   Plugin library descriptor */ mysql_declare_plugin(audit_syslog) {   MYSQL_AUDIT_PLUGIN,           /* plugin type                    */   &audit_syslog_descriptor,     /* descriptor handle               */   "audit_syslog",               /* plugin name                     */   "Author Name",                /* author                          */   "Simple Syslog Audit",        /* description                     */   PLUGIN_LICENSE_GPL,           /* licence                         */   audit_syslog_init,            /* init function     */   audit_syslog_deinit,          /* deinit function */   0x0001,                       /* plugin version                  */   NULL,                         /* status variables        */   NULL,                         /* system variables                */   NULL,                         /* no reserves                     */   0,                            /* no flags                        */ } mysql_declare_plugin_end; The general plugin descriptor above is standard for all plugin types in MySQL. The plugin type is defined along with the init/deinit functions and interface methods into the system for sharing information, and various other metadata information. The descriptors have an internally recognised version number so that plugins can be matched against the api on the running server. The other details are usually related to the type-specific methods and structures to implement the plugin. Each plugin has a type-specific descriptor as well which details how the plugin is implemented for the specific purpose of that plugin type. /*   Plugin type-specific descriptor */ static struct st_mysql_audit audit_syslog_descriptor= {   MYSQL_AUDIT_INTERFACE_VERSION,                        /* interface version    */   NULL,                                                 /* release_thd function */   audit_syslog_notify,                                  /* notify function      */   { (unsigned long) MYSQL_AUDIT_GENERAL_CLASSMASK |                     MYSQL_AUDIT_CONNECTION_CLASSMASK }  /* class mask           */ }; In this particular case, the release_thd function has not been defined as it is not required. The important method for auditing is the notify function which is activated when an event occurs on the system. The notify function is designed to activate on an event and the implementation will determine how it is handled. For the audit_syslog plugin, the use of the syslog feature sends all events to the syslog for recording. The class mask allows us to determine what type of events are being seen by the notify function. There are currently two major types of event: 1. General Events: This includes general logging, errors, status and result type events. This is the main one for tracking the queries and operations on the database. 2. Connection Events: This group is based around user logins. It monitors connections and disconnections, but also if somebody changes user while connected. With most audit plugins, the principle behind the plugin is to track changes to the system over time and counters can be an important part of this process. The next step is to define and initialise the counters that are used to track the events in the service. There are 3 counters defined in total for our plugin - the # of general events, the # of connection events and the total number of events.  static volatile int total_number_of_calls; /* Count MYSQL_AUDIT_GENERAL_CLASS event instances */ static volatile int number_of_calls_general; /* Count MYSQL_AUDIT_CONNECTION_CLASS event instances */ static volatile int number_of_calls_connection; The init and deinit functions for the plugin are there to be called when the plugin is activated and when it is terminated. These offer the best option to initialise the counters for our plugin: /*  Initialize the plugin at server start or plugin installation. */ static int audit_syslog_init(void *arg __attribute__((unused))) {     openlog("mysql_audit:",LOG_PID|LOG_PERROR|LOG_CONS,LOG_USER);     total_number_of_calls= 0;     number_of_calls_general= 0;     number_of_calls_connection= 0;     return(0); } The init function does a call to openlog to initialise the syslog functionality. The parameters are the service to log under ("mysql_audit" in this case), the syslog flags and the facility for the logging. Then each of the counters are initialised to zero and a success is returned. If the init function is not defined, it will return success by default. /*  Terminate the plugin at server shutdown or plugin deinstallation. */ static int audit_syslog_deinit(void *arg __attribute__((unused))) {     closelog();     return(0); } The deinit function will simply close our syslog connection and return success. Note that the syslog functionality is part of the glibc libraries and does not require any external factors.  The function names are what we define in the general plugin structure, so these have to match otherwise there will be errors. The next step is to implement the event notifier function that was defined in the type specific descriptor (audit_syslog_descriptor) which is audit_syslog_notify. /* Event notifier function */ static void audit_syslog_notify(MYSQL_THD thd __attribute__((unused)), unsigned int event_class, const void *event) { total_number_of_calls++; if (event_class == MYSQL_AUDIT_GENERAL_CLASS) { const struct mysql_event_general *event_general= (const struct mysql_event_general *) event; number_of_calls_general++; syslog(audit_loglevel,"%lu: User: %s Command: %s Query: %s\n", event_general->general_thread_id, event_general->general_user, event_general->general_command, event_general->general_query ); } else if (event_class == MYSQL_AUDIT_CONNECTION_CLASS) { const struct mysql_event_connection *event_connection= (const struct mysql_event_connection *) event; number_of_calls_connection++; syslog(audit_loglevel,"%lu: User: %s@%s[%s] Event: %d Status: %d\n", event_connection->thread_id, event_connection->user, event_connection->host, event_connection->ip, event_connection->event_subclass, event_connection->status ); } }   In the case of an event, the notifier function is called. The first step is to increment the total number of events that have occurred in our database.The event argument is then cast into the appropriate event structure depending on the class type, of general event or connection event. The event type counters are incremented and details are sent via the syslog() function out to the system log. There are going to be different line formats and information returned since the general events have different data compared to the connection events, even though some of the details overlap, for example, user, thread id, host etc. On compiling the code now, there should be no errors and the resulting audit_syslog.so can be loaded into the server and ready to use. Log into the server and type: mysql> INSTALL PLUGIN audit_syslog SONAME 'audit_syslog.so'; This will install the plugin and will start updating the syslog immediately. Note that the audit plugin attaches to the immediate thread and cannot be uninstalled while that thread is active. This means that you cannot run the UNISTALL command until you log into a different connection (thread) on the server. Once the plugin is loaded, the system log will show output such as the following: Oct  8 15:33:21 machine mysql_audit:[8337]: 87: User: root[root] @ localhost []  Command: (null)  Query: INSTALL PLUGIN audit_syslog SONAME 'audit_syslog.so' Oct  8 15:33:21 machine mysql_audit:[8337]: 87: User: root[root] @ localhost []  Command: Query  Query: INSTALL PLUGIN audit_syslog SONAME 'audit_syslog.so' Oct  8 15:33:40 machine mysql_audit:[8337]: 87: User: root[root] @ localhost []  Command: (null)  Query: show tables Oct  8 15:33:40 machine mysql_audit:[8337]: 87: User: root[root] @ localhost []  Command: Query  Query: show tables Oct  8 15:33:43 machine mysql_audit:[8337]: 87: User: root[root] @ localhost []  Command: (null)  Query: select * from t1 Oct  8 15:33:43 machine mysql_audit:[8337]: 87: User: root[root] @ localhost []  Command: Query  Query: select * from t1 It appears that two of each event is being shown, but in actuality, these are two separate event types - the result event and the status event. This could be refined further by changing the audit_syslog_notify function to handle the different event sub-types in a different manner.  So far, it seems that the logging is working with events showing up in the syslog output. The issue now is that the counters created earlier to track the number of events by type are not accessible when the plugin is being run. Instead there needs to be a way to expose the plugin specific information to the service and vice versa. This could be done via the information_schema plugin api, but for something as simple as counters, the obvious choice is the system status variables. This is done using the standard structure and the declaration: /*  Plugin status variables for SHOW STATUS */ static struct st_mysql_show_var audit_syslog_status[]= {   { "Audit_syslog_total_calls",     (char *) &total_number_of_calls,     SHOW_INT },   { "Audit_syslog_general_events",     (char *) &number_of_calls_general,     SHOW_INT },   { "Audit_syslog_connection_events",     (char *) &number_of_calls_connection,     SHOW_INT },   { 0, 0, SHOW_INT } };   The structure is simply the name that will be displaying in the mysql service, the address of the associated variables, and the data type being used for the counter. It is finished with a blank structure to show that there are no more variables. Remember that status variables may have the same name for variables from other plugin, so it is considered appropriate to add the plugin name at the start of the status variable name to avoid confusion. Looking at the status variables in the mysql client shows something like the following: mysql> show global status like "audit%"; +--------------------------------+-------+ | Variable_name                  | Value | +--------------------------------+-------+ | Audit_syslog_connection_events | 1     | | Audit_syslog_general_events    | 2     | | Audit_syslog_total_calls       | 3     | +--------------------------------+-------+ 3 rows in set (0.00 sec) The final connectivity piece for the plugin is to allow the interactive change of the logging level between the plugin and the system. This requires the ability to send changes via the mysql service through to the plugin. This is done using the system variables interface and defining a single variable to keep track of the active logging level for the facility. /* Plugin system variables for SHOW VARIABLES */ static MYSQL_SYSVAR_STR(loglevel, audit_loglevel,                         PLUGIN_VAR_RQCMDARG,                         "User can specify the log level for auditing",                         audit_loglevel_check, audit_loglevel_update, "LOG_NOTICE"); static struct st_mysql_sys_var* audit_syslog_sysvars[] = {     MYSQL_SYSVAR(loglevel),     NULL }; So now the system variable 'loglevel' is defined for the plugin and associated to the global variable 'audit_loglevel'. The check or validation function is defined to make sure that no garbage values are attempted in the update of the variable. The update function is used to save the new value to the variable. Note that the audit_syslog_sysvars structure is defined in the general plugin descriptor to associate the link between the plugin and the system and how much they interact. Next comes the implementation of the validation function and the update function for the system variable. It is worth noting that if you have a simple numeric such as integers for the variable types, the validate function is often not required as MySQL will handle the automatic check and validation of simple types. /* longest valid value */ #define MAX_LOGLEVEL_SIZE 100 /* hold the valid values */ static const char *possible_modes[]= { "LOG_ERROR", "LOG_WARNING", "LOG_NOTICE", NULL };  static int audit_loglevel_check(     THD*                        thd,    /*!< in: thread handle */     struct st_mysql_sys_var*    var,    /*!< in: pointer to system                                         variable */     void*                       save,   /*!< out: immediate result                                         for update function */     struct st_mysql_value*      value)  /*!< in: incoming string */ {     char buff[MAX_LOGLEVEL_SIZE];     const char *str;     const char **found;     int length;     length= sizeof(buff);     if (!(str= value->val_str(value, buff, &length)))         return 1;     /*         We need to return a pointer to a locally allocated value in "save".         Here we pick to search for the supplied value in an global array of         constant strings and return a pointer to one of them.         The other possiblity is to use the thd_alloc() function to allocate         a thread local buffer instead of the global constants.     */     for (found= possible_modes; *found; found++)     {         if (!strcmp(*found, str))         {             *(const char**)save= *found;             return 0;         }     }     return 1; } The validation function is simply to take the value being passed in via the SET GLOBAL VARIABLE command and check if it is one of the pre-defined values allowed  in our possible_values array. If it is found to be valid, then the value is assigned to the save variable ready for passing through to the update function. static void audit_loglevel_update(     THD*                        thd,        /*!< in: thread handle */     struct st_mysql_sys_var*    var,        /*!< in: system variable                                             being altered */     void*                       var_ptr,    /*!< out: pointer to                                             dynamic variable */     const void*                 save)       /*!< in: pointer to                                             temporary storage */ {     /* assign the new value so that the server can read it */     *(char **) var_ptr= *(char **) save;     /* assign the new value to the internal variable */     audit_loglevel= *(char **) save; } Since all the validation has been done already, the update function is quite simple for this plugin. The first part is to update the system variable pointer so that the server can read the value. The second part is to update our own global plugin variable for tracking the value. Notice that the save variable is passed in as a void type to allow handling of various data types, so it must be cast to the appropriate data type when assigning it to the variables. Looking at how the latest changes affect the usage of the plugin and the interaction within the server shows: mysql> show global variables like "audit%"; +-----------------------+------------+ | Variable_name         | Value      | +-----------------------+------------+ | audit_syslog_loglevel | LOG_NOTICE | +-----------------------+------------+ 1 row in set (0.00 sec) mysql> set global audit_syslog_loglevel="LOG_ERROR"; Query OK, 0 rows affected (0.00 sec) mysql> show global status like "audit%"; +--------------------------------+-------+ | Variable_name                  | Value | +--------------------------------+-------+ | Audit_syslog_connection_events | 1     | | Audit_syslog_general_events    | 11    | | Audit_syslog_total_calls       | 12    | +--------------------------------+-------+ 3 rows in set (0.00 sec) mysql> show global variables like "audit%"; +-----------------------+-----------+ | Variable_name         | Value     | +-----------------------+-----------+ | audit_syslog_loglevel | LOG_ERROR | +-----------------------+-----------+ 1 row in set (0.00 sec)   So now we have a plugin that will audit the events on the system and log the details to the system log. It allows for interaction to see the number of different events within the server details and provides a mechanism to change the logging level interactively via the standard system methods of the SET command. A more complex auditing plugin may have more detailed code, but each of the above areas is what will be involved and simply expanded on to add more functionality. With the above skeleton code, it is now possible to create your own audit plugins to implement your own auditing requirements. If, however, you are not of the coding persuasion, then you could always consider the option of the MySQL Enterprise Audit plugin that is available to purchase.

    Read the article

  • Metro: Creating an IndexedDbDataSource for WinJS

    - by Stephen.Walther
    The goal of this blog entry is to describe how you can create custom data sources which you can use with the controls in the WinJS library. In particular, I explain how you can create an IndexedDbDataSource which you can use to store and retrieve data from an IndexedDB database. If you want to skip ahead, and ignore all of the fascinating content in-between, I’ve included the complete code for the IndexedDbDataSource at the very bottom of this blog entry. What is IndexedDB? IndexedDB is a database in the browser. You can use the IndexedDB API with all modern browsers including Firefox, Chrome, and Internet Explorer 10. And, of course, you can use IndexedDB with Metro style apps written with JavaScript. If you need to persist data in a Metro style app written with JavaScript then IndexedDB is a good option. Each Metro app can only interact with its own IndexedDB databases. And, IndexedDB provides you with transactions, indices, and cursors – the elements of any modern database. An IndexedDB database might be different than the type of database that you normally use. An IndexedDB database is an object-oriented database and not a relational database. Instead of storing data in tables, you store data in object stores. You store JavaScript objects in an IndexedDB object store. You create new IndexedDB object stores by handling the upgradeneeded event when you attempt to open a connection to an IndexedDB database. For example, here’s how you would both open a connection to an existing database named TasksDB and create the TasksDB database when it does not already exist: var reqOpen = window.indexedDB.open(“TasksDB”, 2); reqOpen.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true }); }; reqOpen.onsuccess = function () { var db = reqOpen.result; // Do something with db }; When you call window.indexedDB.open(), and the database does not already exist, then the upgradeneeded event is raised. In the code above, the upgradeneeded handler creates a new object store named tasks. The new object store has an auto-increment column named id which acts as the primary key column. If the database already exists with the right version, and you call window.indexedDB.open(), then the success event is raised. At that point, you have an open connection to the existing database and you can start doing something with the database. You use asynchronous methods to interact with an IndexedDB database. For example, the following code illustrates how you would add a new object to the tasks object store: var transaction = db.transaction(“tasks”, “readwrite”); var reqAdd = transaction.objectStore(“tasks”).add({ name: “Feed the dog” }); reqAdd.onsuccess = function() { // Tasks added successfully }; The code above creates a new database transaction, adds a new task to the tasks object store, and handles the success event. If the new task gets added successfully then the success event is raised. Creating a WinJS IndexedDbDataSource The most powerful control in the WinJS library is the ListView control. This is the control that you use to display a collection of items. If you want to display data with a ListView control, you need to bind the control to a data source. The WinJS library includes two objects which you can use as a data source: the List object and the StorageDataSource object. The List object enables you to represent a JavaScript array as a data source and the StorageDataSource enables you to represent the file system as a data source. If you want to bind an IndexedDB database to a ListView then you have a choice. You can either dump the items from the IndexedDB database into a List object or you can create a custom data source. I explored the first approach in a previous blog entry. In this blog entry, I explain how you can create a custom IndexedDB data source. Implementing the IListDataSource Interface You create a custom data source by implementing the IListDataSource interface. This interface contains the contract for the methods which the ListView needs to interact with a data source. The easiest way to implement the IListDataSource interface is to derive a new object from the base VirtualizedDataSource object. The VirtualizedDataSource object requires a data adapter which implements the IListDataAdapter interface. Yes, because of the number of objects involved, this is a little confusing. Your code ends up looking something like this: var IndexedDbDataSource = WinJS.Class.derive( WinJS.UI.VirtualizedDataSource, function (dbName, dbVersion, objectStoreName, upgrade, error) { this._adapter = new IndexedDbDataAdapter(dbName, dbVersion, objectStoreName, upgrade, error); this._baseDataSourceConstructor(this._adapter); }, { nuke: function () { this._adapter.nuke(); }, remove: function (key) { this._adapter.removeInternal(key); } } ); The code above is used to create a new class named IndexedDbDataSource which derives from the base VirtualizedDataSource class. In the constructor for the new class, the base class _baseDataSourceConstructor() method is called. A data adapter is passed to the _baseDataSourceConstructor() method. The code above creates a new method exposed by the IndexedDbDataSource named nuke(). The nuke() method deletes all of the objects from an object store. The code above also overrides a method named remove(). Our derived remove() method accepts any type of key and removes the matching item from the object store. Almost all of the work of creating a custom data source goes into building the data adapter class. The data adapter class implements the IListDataAdapter interface which contains the following methods: · change() · getCount() · insertAfter() · insertAtEnd() · insertAtStart() · insertBefore() · itemsFromDescription() · itemsFromEnd() · itemsFromIndex() · itemsFromKey() · itemsFromStart() · itemSignature() · moveAfter() · moveBefore() · moveToEnd() · moveToStart() · remove() · setNotificationHandler() · compareByIdentity Fortunately, you are not required to implement all of these methods. You only need to implement the methods that you actually need. In the case of the IndexedDbDataSource, I implemented the getCount(), itemsFromIndex(), insertAtEnd(), and remove() methods. If you are creating a read-only data source then you really only need to implement the getCount() and itemsFromIndex() methods. Implementing the getCount() Method The getCount() method returns the total number of items from the data source. So, if you are storing 10,000 items in an object store then this method would return the value 10,000. Here’s how I implemented the getCount() method: getCount: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore().then(function (store) { var reqCount = store.count(); reqCount.onerror = that._error; reqCount.onsuccess = function (evt) { complete(evt.target.result); }; }); }); } The first thing that you should notice is that the getCount() method returns a WinJS promise. This is a requirement. The getCount() method is asynchronous which is a good thing because all of the IndexedDB methods (at least the methods implemented in current browsers) are also asynchronous. The code above retrieves an object store and then uses the IndexedDB count() method to get a count of the items in the object store. The value is returned from the promise by calling complete(). Implementing the itemsFromIndex method When a ListView displays its items, it calls the itemsFromIndex() method. By default, it calls this method multiple times to get different ranges of items. Three parameters are passed to the itemsFromIndex() method: the requestIndex, countBefore, and countAfter parameters. The requestIndex indicates the index of the item from the database to show. The countBefore and countAfter parameters represent hints. These are integer values which represent the number of items before and after the requestIndex to retrieve. Again, these are only hints and you can return as many items before and after the request index as you please. Here’s how I implemented the itemsFromIndex method: itemsFromIndex: function (requestIndex, countBefore, countAfter) { var that = this; return new WinJS.Promise(function (complete, error) { that.getCount().then(function (count) { if (requestIndex >= count) { return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist)); } var startIndex = Math.max(0, requestIndex - countBefore); var endIndex = Math.min(count, requestIndex + countAfter + 1); that._getObjectStore().then(function (store) { var index = 0; var items = []; var req = store.openCursor(); req.onerror = that._error; req.onsuccess = function (evt) { var cursor = evt.target.result; if (index < startIndex) { index = startIndex; cursor.advance(startIndex); return; } if (cursor && index < endIndex) { index++; items.push({ key: cursor.value[store.keyPath].toString(), data: cursor.value }); cursor.continue(); return; } results = { items: items, offset: requestIndex - startIndex, totalCount: count }; complete(results); }; }); }); }); } In the code above, a cursor is used to iterate through the objects in an object store. You fetch the next item in the cursor by calling either the cursor.continue() or cursor.advance() method. The continue() method moves forward by one object and the advance() method moves forward a specified number of objects. Each time you call continue() or advance(), the success event is raised again. If the cursor is null then you know that you have reached the end of the cursor and you can return the results. Some things to be careful about here. First, the return value from the itemsFromIndex() method must implement the IFetchResult interface. In particular, you must return an object which has an items, offset, and totalCount property. Second, each item in the items array must implement the IListItem interface. Each item should have a key and a data property. Implementing the insertAtEnd() Method When creating the IndexedDbDataSource, I wanted to go beyond creating a simple read-only data source and support inserting and deleting objects. If you want to support adding new items with your data source then you need to implement the insertAtEnd() method. Here’s how I implemented the insertAtEnd() method for the IndexedDbDataSource: insertAtEnd:function(unused, data) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function(store) { var reqAdd = store.add(data); reqAdd.onerror = that._error; reqAdd.onsuccess = function (evt) { var reqGet = store.get(evt.target.result); reqGet.onerror = that._error; reqGet.onsuccess = function (evt) { var newItem = { key:evt.target.result[store.keyPath].toString(), data:evt.target.result } complete(newItem); }; }; }); }); } When implementing the insertAtEnd() method, you need to be careful to return an object which implements the IItem interface. In particular, you should return an object that has a key and a data property. The key must be a string and it uniquely represents the new item added to the data source. The value of the data property represents the new item itself. Implementing the remove() Method Finally, you use the remove() method to remove an item from the data source. You call the remove() method with the key of the item which you want to remove. Implementing the remove() method in the case of the IndexedDbDataSource was a little tricky. The problem is that an IndexedDB object store uses an integer key and the VirtualizedDataSource requires a string key. For that reason, I needed to override the remove() method in the derived IndexedDbDataSource class like this: var IndexedDbDataSource = WinJS.Class.derive( WinJS.UI.VirtualizedDataSource, function (dbName, dbVersion, objectStoreName, upgrade, error) { this._adapter = new IndexedDbDataAdapter(dbName, dbVersion, objectStoreName, upgrade, error); this._baseDataSourceConstructor(this._adapter); }, { nuke: function () { this._adapter.nuke(); }, remove: function (key) { this._adapter.removeInternal(key); } } ); When you call remove(), you end up calling a method of the IndexedDbDataAdapter named removeInternal() . Here’s what the removeInternal() method looks like: setNotificationHandler: function (notificationHandler) { this._notificationHandler = notificationHandler; }, removeInternal: function(key) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqDelete = store.delete (key); reqDelete.onerror = that._error; reqDelete.onsuccess = function (evt) { that._notificationHandler.removed(key.toString()); complete(); }; }); }); } The removeInternal() method calls the IndexedDB delete() method to delete an item from the object store. If the item is deleted successfully then the _notificationHandler.remove() method is called. Because we are not implementing the standard IListDataAdapter remove() method, we need to notify the data source (and the ListView control bound to the data source) that an item has been removed. The way that you notify the data source is by calling the _notificationHandler.remove() method. Notice that we get the _notificationHandler in the code above by implementing another method in the IListDataAdapter interface: the setNotificationHandler() method. You can raise the following types of notifications using the _notificationHandler: · beginNotifications() · changed() · endNotifications() · inserted() · invalidateAll() · moved() · removed() · reload() These methods are all part of the IListDataNotificationHandler interface in the WinJS library. Implementing the nuke() Method I wanted to implement a method which would remove all of the items from an object store. Therefore, I created a method named nuke() which calls the IndexedDB clear() method: nuke: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqClear = store.clear(); reqClear.onerror = that._error; reqClear.onsuccess = function (evt) { that._notificationHandler.reload(); complete(); }; }); }); } Notice that the nuke() method calls the _notificationHandler.reload() method to notify the ListView to reload all of the items from its data source. Because we are implementing a custom method here, we need to use the _notificationHandler to send an update. Using the IndexedDbDataSource To illustrate how you can use the IndexedDbDataSource, I created a simple task list app. You can add new tasks, delete existing tasks, and nuke all of the tasks. You delete an item by selecting an item (swipe or right-click) and clicking the Delete button. Here’s the HTML page which contains the ListView, the form for adding new tasks, and the buttons for deleting and nuking tasks: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>DataSources</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script> <script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script> <!-- DataSources references --> <link href="indexedDb.css" rel="stylesheet" /> <script type="text/javascript" src="indexedDbDataSource.js"></script> <script src="indexedDb.js"></script> </head> <body> <div id="tmplTask" data-win-control="WinJS.Binding.Template"> <div class="taskItem"> Id: <span data-win-bind="innerText:id"></span> <br /><br /> Name: <span data-win-bind="innerText:name"></span> </div> </div> <div id="lvTasks" data-win-control="WinJS.UI.ListView" data-win-options="{ itemTemplate: select('#tmplTask'), selectionMode: 'single' }"></div> <form id="frmAdd"> <fieldset> <legend>Add Task</legend> <label>New Task</label> <input id="inputTaskName" required /> <button>Add</button> </fieldset> </form> <button id="btnNuke">Nuke</button> <button id="btnDelete">Delete</button> </body> </html> And here is the JavaScript code for the TaskList app: /// <reference path="//Microsoft.WinJS.1.0.RC/js/base.js" /> /// <reference path="//Microsoft.WinJS.1.0.RC/js/ui.js" /> function init() { WinJS.UI.processAll().done(function () { var lvTasks = document.getElementById("lvTasks").winControl; // Bind the ListView to its data source var tasksDataSource = new DataSources.IndexedDbDataSource("TasksDB", 1, "tasks", upgrade); lvTasks.itemDataSource = tasksDataSource; // Wire-up Add, Delete, Nuke buttons document.getElementById("frmAdd").addEventListener("submit", function (evt) { evt.preventDefault(); tasksDataSource.beginEdits(); tasksDataSource.insertAtEnd(null, { name: document.getElementById("inputTaskName").value }).done(function (newItem) { tasksDataSource.endEdits(); document.getElementById("frmAdd").reset(); lvTasks.ensureVisible(newItem.index); }); }); document.getElementById("btnDelete").addEventListener("click", function () { if (lvTasks.selection.count() == 1) { lvTasks.selection.getItems().done(function (items) { tasksDataSource.remove(items[0].data.id); }); } }); document.getElementById("btnNuke").addEventListener("click", function () { tasksDataSource.nuke(); }); // This method is called to initialize the IndexedDb database function upgrade(evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true }); } }); } document.addEventListener("DOMContentLoaded", init); The IndexedDbDataSource is created and bound to the ListView control with the following two lines of code: var tasksDataSource = new DataSources.IndexedDbDataSource("TasksDB", 1, "tasks", upgrade); lvTasks.itemDataSource = tasksDataSource; The IndexedDbDataSource is created with four parameters: the name of the database to create, the version of the database to create, the name of the object store to create, and a function which contains code to initialize the new database. The upgrade function creates a new object store named tasks with an auto-increment property named id: function upgrade(evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true }); } The Complete Code for the IndexedDbDataSource Here’s the complete code for the IndexedDbDataSource: (function () { /************************************************ * The IndexedDBDataAdapter enables you to work * with a HTML5 IndexedDB database. *************************************************/ var IndexedDbDataAdapter = WinJS.Class.define( function (dbName, dbVersion, objectStoreName, upgrade, error) { this._dbName = dbName; // database name this._dbVersion = dbVersion; // database version this._objectStoreName = objectStoreName; // object store name this._upgrade = upgrade; // database upgrade script this._error = error || function (evt) { console.log(evt.message); }; }, { /******************************************* * IListDataAdapter Interface Methods ********************************************/ getCount: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore().then(function (store) { var reqCount = store.count(); reqCount.onerror = that._error; reqCount.onsuccess = function (evt) { complete(evt.target.result); }; }); }); }, itemsFromIndex: function (requestIndex, countBefore, countAfter) { var that = this; return new WinJS.Promise(function (complete, error) { that.getCount().then(function (count) { if (requestIndex >= count) { return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist)); } var startIndex = Math.max(0, requestIndex - countBefore); var endIndex = Math.min(count, requestIndex + countAfter + 1); that._getObjectStore().then(function (store) { var index = 0; var items = []; var req = store.openCursor(); req.onerror = that._error; req.onsuccess = function (evt) { var cursor = evt.target.result; if (index < startIndex) { index = startIndex; cursor.advance(startIndex); return; } if (cursor && index < endIndex) { index++; items.push({ key: cursor.value[store.keyPath].toString(), data: cursor.value }); cursor.continue(); return; } results = { items: items, offset: requestIndex - startIndex, totalCount: count }; complete(results); }; }); }); }); }, insertAtEnd:function(unused, data) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function(store) { var reqAdd = store.add(data); reqAdd.onerror = that._error; reqAdd.onsuccess = function (evt) { var reqGet = store.get(evt.target.result); reqGet.onerror = that._error; reqGet.onsuccess = function (evt) { var newItem = { key:evt.target.result[store.keyPath].toString(), data:evt.target.result } complete(newItem); }; }; }); }); }, setNotificationHandler: function (notificationHandler) { this._notificationHandler = notificationHandler; }, /***************************************** * IndexedDbDataSource Method ******************************************/ removeInternal: function(key) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqDelete = store.delete (key); reqDelete.onerror = that._error; reqDelete.onsuccess = function (evt) { that._notificationHandler.removed(key.toString()); complete(); }; }); }); }, nuke: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqClear = store.clear(); reqClear.onerror = that._error; reqClear.onsuccess = function (evt) { that._notificationHandler.reload(); complete(); }; }); }); }, /******************************************* * Private Methods ********************************************/ _ensureDbOpen: function () { var that = this; // Try to get cached Db if (that._cachedDb) { return WinJS.Promise.wrap(that._cachedDb); } // Otherwise, open the database return new WinJS.Promise(function (complete, error, progress) { var reqOpen = window.indexedDB.open(that._dbName, that._dbVersion); reqOpen.onerror = function (evt) { error(); }; reqOpen.onupgradeneeded = function (evt) { that._upgrade(evt); that._notificationHandler.invalidateAll(); }; reqOpen.onsuccess = function () { that._cachedDb = reqOpen.result; complete(that._cachedDb); }; }); }, _getObjectStore: function (type) { type = type || "readonly"; var that = this; return new WinJS.Promise(function (complete, error) { that._ensureDbOpen().then(function (db) { var transaction = db.transaction(that._objectStoreName, type); complete(transaction.objectStore(that._objectStoreName)); }); }); }, _get: function (key) { return new WinJS.Promise(function (complete, error) { that._getObjectStore().done(function (store) { var reqGet = store.get(key); reqGet.onerror = that._error; reqGet.onsuccess = function (item) { complete(item); }; }); }); } } ); var IndexedDbDataSource = WinJS.Class.derive( WinJS.UI.VirtualizedDataSource, function (dbName, dbVersion, objectStoreName, upgrade, error) { this._adapter = new IndexedDbDataAdapter(dbName, dbVersion, objectStoreName, upgrade, error); this._baseDataSourceConstructor(this._adapter); }, { nuke: function () { this._adapter.nuke(); }, remove: function (key) { this._adapter.removeInternal(key); } } ); WinJS.Namespace.define("DataSources", { IndexedDbDataSource: IndexedDbDataSource }); })(); Summary In this blog post, I provided an overview of how you can create a new data source which you can use with the WinJS library. I described how you can create an IndexedDbDataSource which you can use to bind a ListView control to an IndexedDB database. While describing how you can create a custom data source, I explained how you can implement the IListDataAdapter interface. You also learned how to raise notifications — such as a removed or invalidateAll notification — by taking advantage of the methods of the IListDataNotificationHandler interface.

    Read the article

  • Scrolling an HTML 5 page using JQuery

    - by nikolaosk
    In this post I will show you how to use JQuery to scroll through an HTML 5 page.I had to help a friend of mine to implement this functionality and I thought it would be a good idea to write a post.I will not use any JQuery scrollbar plugin,I will just use the very popular JQuery Library. Please download the library (minified version) from http://jquery.com/download.Please find here all my posts regarding JQuery.Also have a look at my posts regarding HTML 5.In order to be absolutely clear this is not (and could not be) a detailed tutorial on HTML 5. There are other great resources for that.Navigate to the excellent interactive tutorials of W3School.Another excellent resource is HTML 5 Doctor.Two very nice sites that show you what features and specifications are implemented by various browsers and their versions are http://caniuse.com/ and http://html5test.com/. At this times Chrome seems to support most of HTML 5 specifications.Another excellent way to find out if the browser supports HTML 5 and CSS 3 features is to use the Javascript lightweight library Modernizr.In this hands-on example I will be using Expression Web 4.0.This application is not a free application. You can use any HTML editor you like.You can use Visual Studio 2012 Express edition. You can download it here. Let me move on to the actual example.This is the sample HTML 5 page<!DOCTYPE html><html lang="en">  <head>    <title>Liverpool Legends</title>        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >        <link rel="stylesheet" type="text/css" href="style.css">        <script type="text/javascript" src="jquery-1.8.2.min.js"> </script>     <script type="text/javascript" src="scroll.js">     </script>       </head>  <body>    <header>        <h1>Liverpool Legends</h1>    </header>        <div id="main">        <table>        <caption>Liverpool Players</caption>        <thead>            <tr>                <th>Name</th>                <th>Photo</th>                <th>Position</th>                <th>Age</th>                <th>Scroll</th>            </tr>        </thead>        <tfoot class="footnote">            <tr>                <td colspan="4">We will add more photos soon</td>            </tr>        </tfoot>    <tbody>        <tr class="maintop">        <td>Alan Hansen</td>            <td>            <figure>            <img src="images\Alan-hansen-large.jpg" alt="Alan Hansen">            <figcaption>The best Liverpool Defender <a href="http://en.wikipedia.org/wiki/Alan_Hansen">Alan Hansen</a></figcaption>            </figure>            </td>            <td>Defender</td>            <td>57</td>            <td class="top">Middle</td>        </tr>        <tr>        <td>Graeme Souness</td>            <td>            <figure>            <img src="images\graeme-souness-large.jpg" alt="Graeme Souness">            <figcaption>Souness was the captain of the successful Liverpool team of the early 1980s <a href="http://en.wikipedia.org/wiki/Graeme_Souness">Graeme Souness</a></figcaption>            </figure>            </td>            <td>MidFielder</td>            <td>59</td>        </tr>        <tr>        <td>Ian Rush</td>            <td>            <figure>            <img src="images\ian-rush-large.jpg" alt="Ian Rush">            <figcaption>The deadliest Liverpool Striker <a href="http://it.wikipedia.org/wiki/Ian_Rush">Ian Rush</a></figcaption>            </figure>            </td>            <td>Striker</td>            <td>51</td>        </tr>        <tr class="mainmiddle">        <td>John Barnes</td>            <td>            <figure>            <img src="images\john-barnes-large.jpg" alt="John Barnes">            <figcaption>The best Liverpool Defender <a href="http://en.wikipedia.org/wiki/John_Barnes_(footballer)">John Barnes</a></figcaption>            </figure>            </td>            <td>MidFielder</td>            <td>49</td>            <td class="middle">Bottom</td>        </tr>                <tr>        <td>Kenny Dalglish</td>            <td>            <figure>            <img src="images\kenny-dalglish-large.jpg" alt="Kenny Dalglish">            <figcaption>King Kenny <a href="http://en.wikipedia.org/wiki/Kenny_Dalglish">Kenny Dalglish</a></figcaption>            </figure>            </td>            <td>Midfielder</td>            <td>61</td>        </tr>        <tr>            <td>Michael Owen</td>            <td>            <figure>            <img src="images\michael-owen-large.jpg" alt="Michael Owen">            <figcaption>Michael was Liverpool's top goal scorer from 1997–2004 <a href="http://www.michaelowen.com/">Michael Owen</a></figcaption>            </figure>            </td>            <td>Striker</td>            <td>33</td>        </tr>        <tr>            <td>Robbie Fowler</td>            <td>            <figure>            <img src="images\robbie-fowler-large.jpg" alt="Robbie Fowler">            <figcaption>Fowler scored 183 goals in total for Liverpool <a href="http://en.wikipedia.org/wiki/Robbie_Fowler">Robbie Fowler</a></figcaption>            </figure>            </td>            <td>Striker</td>            <td>38</td>        </tr>        <tr class="mainbottom">            <td>Steven Gerrard</td>            <td>            <figure>            <img src="images\steven-gerrard-large.jpg" alt="Steven Gerrard">            <figcaption>Liverpool's captain <a href="http://en.wikipedia.org/wiki/Steven_Gerrard">Steven Gerrard</a></figcaption>            </figure>            </td>            <td>Midfielder</td>            <td>32</td>            <td class="bottom">Top</td>        </tr>    </tbody></table>          </div>            <footer>        <p>All Rights Reserved</p>      </footer>     </body>  </html>  The markup is very easy to follow and understand. You do not have to type all the code,simply copy and paste it.For those that you are not familiar with HTML 5, please take a closer look at the new tags/elements introduced with HTML 5.When I view the HTML 5 page with Firefox I see the following result. I have also an external stylesheet (style.css). body{background-color:#efefef;}h1{font-size:2.3em;}table { border-collapse: collapse;font-family: Futura, Arial, sans-serif; }caption { font-size: 1.2em; margin: 1em auto; }th, td {padding: .65em; }th, thead { background: #000; color: #fff; border: 1px solid #000; }tr:nth-child(odd) { background: #ccc; }tr:nth-child(even) { background: #404040; }td { border-right: 1px solid #777; }table { border: 1px solid #777;  }.top, .middle, .bottom {    cursor: pointer;    font-size: 22px;    font-weight: bold;    text-align: center;}.footnote{text-align:center;font-family:Tahoma;color:#EB7515;}a{color:#22577a;text-decoration:none;}     a:hover {color:#125949; text-decoration:none;}  footer{background-color:#505050;width:1150px;}These are just simple CSS Rules that style the various HTML 5 tags,classes. The jQuery code that makes it all possible resides inside the scroll.js file.Make sure you type everything correctly.$(document).ready(function() {                 $('.top').click(function(){                     $('html, body').animate({                         scrollTop: $(".mainmiddle").offset().top                     },4000 );                  });                 $('.middle').click(function(){                     $('html, body').animate({                         scrollTop: $(".mainbottom").offset().top                     },4000);                  });                     $('.bottom').click(function(){                     $('html, body').animate({                         scrollTop: $(".maintop").offset().top                     },4000);                  }); });  Let me explain what I am doing here.When I click on the Middle word (  $('.top').click(function(){ ) this relates to the top class that is clicked.Then we declare the elements that we want to participate in the scrolling. In this case is html,body ( $('html, body').animate).These elements will be part of the vertical scrolling.In the next line of code we simply move (navigate) to the element (class mainmiddle that is attached to a tr element.)      scrollTop: $(".mainmiddle").offset().top  Make sure you type all the code correctly and try it for yourself. I have tested this solution will all 4-5 major browsers.Hope it helps!!!

    Read the article

  • Creating a thematic map

    - by jsharma
    This post describes how to create a simple thematic map, just a state population layer, with no underlying map tile layer. The map shows states color-coded by total population. The map is interactive with info-windows and can be panned and zoomed. The sample code demonstrates the following: Displaying an interactive vector layer with no background map tile layer (i.e. purpose and use of the Universe object) Using a dynamic (i.e. defined via the javascript client API) color bucket style Dynamically changing a layer's rendering style Specifying which attribute value to use in determining the bucket, and hence style, for a feature (FoI) The result is shown in the screenshot below. The states layer was defined, and stored in the user_sdo_themes view of the mvdemo schema, using MapBuilder. The underlying table is defined as SQL> desc states_32775  Name                                      Null?    Type ----------------------------------------- -------- ----------------------------  STATE                                              VARCHAR2(26)  STATE_ABRV                                         VARCHAR2(2) FIPSST                                             VARCHAR2(2) TOTPOP                                             NUMBER PCTSMPLD                                           NUMBER LANDSQMI                                           NUMBER POPPSQMI                                           NUMBER ... MEDHHINC NUMBER AVGHHINC NUMBER GEOM32775 MDSYS.SDO_GEOMETRY We'll use the TOTPOP column value in the advanced (color bucket) style for rendering the states layers. The predefined theme (US_STATES_BI) is defined as follows. SQL> select styling_rules from user_sdo_themes where name='US_STATES_BI'; STYLING_RULES -------------------------------------------------------------------------------- <?xml version="1.0" standalone="yes"?> <styling_rules highlight_style="C.CB_QUAL_8_CLASS_DARK2_1"> <hidden_info> <field column="STATE" name="Name"/> <field column="POPPSQMI" name="POPPSQMI"/> <field column="TOTPOP" name="TOTPOP"/> </hidden_info> <rule column="TOTPOP"> <features style="states_totpop"> </features> <label column="STATE_ABRV" style="T.BLUE_SERIF_10"> 1 </label> </rule> </styling_rules> SQL> The theme definition specifies that the state, poppsqmi, totpop, state_abrv, and geom columns will be queried from the states_32775 table. The state_abrv value will be used to label the state while the totpop value will be used to determine the color-fill from those defined in the states_totpop advanced style. The states_totpop style, which we will not use in our demo, is defined as shown below. SQL> select definition from user_sdo_styles where name='STATES_TOTPOP'; DEFINITION -------------------------------------------------------------------------------- <?xml version="1.0" ?> <AdvancedStyle> <BucketStyle> <Buckets default_style="C.S02_COUNTRY_AREA"> <RangedBucket seq="0" label="10K - 5M" low="10000" high="5000000" style="C.SEQ6_01" /> <RangedBucket seq="1" label="5M - 12M" low="5000001" high="1.2E7" style="C.SEQ6_02" /> <RangedBucket seq="2" label="12M - 20M" low="1.2000001E7" high="2.0E7" style="C.SEQ6_04" /> <RangedBucket seq="3" label="&gt; 20M" low="2.0000001E7" high="5.0E7" style="C.SEQ6_05" /> </Buckets> </BucketStyle> </AdvancedStyle> SQL> The demo defines additional advanced styles via the OM.style object and methods and uses those instead when rendering the states layer.   Now let's look at relevant snippets of code that defines the map extent and zoom levels (i.e. the OM.universe),  loads the states predefined vector layer (OM.layer), and sets up the advanced (color bucket) style. Defining the map extent and zoom levels. function initMap() {   //alert("Initialize map view");     // define the map extent and number of zoom levels.   // The Universe object is similar to the map tile layer configuration   // It defines the map extent, number of zoom levels, and spatial reference system   // well-known ones (like web mercator/google/bing or maps.oracle/elocation are predefined   // The Universe must be defined when there is no underlying map tile layer.   // When there is a map tile layer then that defines the map extent, srid, and zoom levels.      var uni= new OM.universe.Universe(     {         srid : 32775,         bounds : new OM.geometry.Rectangle(                         -3280000, 170000, 2300000, 3200000, 32775),         numberOfZoomLevels: 8     }); The srid specifies the spatial reference system which is Equal-Area Projection (United States). SQL> select cs_name from cs_srs where srid=32775 ; CS_NAME --------------------------------------------------- Equal-Area Projection (United States) The bounds defines the map extent. It is a Rectangle defined using the lower-left and upper-right coordinates and srid. Loading and displaying the states layer This is done in the states() function. The full code is at the end of this post, however here's the snippet which defines the states VectorLayer.     // States is a predefined layer in user_sdo_themes     var  layer2 = new OM.layer.VectorLayer("vLayer2",     {         def:         {             type:OM.layer.VectorLayer.TYPE_PREDEFINED,             dataSource:"mvdemo",             theme:"us_states_bi",             url: baseURL,             loadOnDemand: false         },         boundingTheme:true      }); The first parameter is a layer name, the second is an object literal for a layer config. The config object has two attributes: the first is the layer definition, the second specifies whether the layer is a bounding one (i.e. used to determine the current map zoom and center such that the whole layer is displayed within the map window) or not. The layer config has the following attributes: type - specifies whether is a predefined one, a defined via a SQL query (JDBC), or in a json-format file (DATAPACK) theme - is the predefined theme's name url - is the location of the mapviewer server loadOnDemand - specifies whether to load all the features or just those that lie within the current map window and load additional ones as needed on a pan or zoom The code snippet below dynamically defines an advanced style and then uses it, instead of the 'states_totpop' style, when rendering the states layer. // override predefined rendering style with programmatic one    var theRenderingStyle =      createBucketColorStyle('YlBr5', colorSeries, 'States5', true);   // specify which attribute is used in determining the bucket (i.e. color) to use for the state   // It can be an array because the style could be a chart type (pie/bar)   // which requires multiple attribute columns     // Use the STATE.TOTPOP column (aka attribute) value here    layer2.setRenderingStyle(theRenderingStyle, ["TOTPOP"]); The style itself is defined in the createBucketColorStyle() function. Dynamically defining an advanced style The advanced style used here is a bucket color style, i.e. a color style is associated with each bucket. So first we define the colors and then the buckets.     numClasses = colorSeries[colorName].classes;    // create Color Styles    for (var i=0; i < numClasses; i++)    {         theStyles[i] = new OM.style.Color(                      {fill: colorSeries[colorName].fill[i],                        stroke:colorSeries[colorName].stroke[i],                       strokeOpacity: useGradient? 0.25 : 1                      });    }; numClasses is the number of buckets. The colorSeries array contains the color fill and stroke definitions and is: var colorSeries = { //multi-hue color scheme #10 YlBl. "YlBl3": {   classes:3,                  fill: [0xEDF8B1, 0x7FCDBB, 0x2C7FB8],                  stroke:[0xB5DF9F, 0x72B8A8, 0x2872A6]   }, "YlBl5": {   classes:5,                  fill:[0xFFFFCC, 0xA1DAB4, 0x41B6C4, 0x2C7FB8, 0x253494],                  stroke:[0xE6E6B8, 0x91BCA2, 0x3AA4B0, 0x2872A6, 0x212F85]   }, //multi-hue color scheme #11 YlBr.  "YlBr3": {classes:3,                  fill:[0xFFF7BC, 0xFEC44F, 0xD95F0E],                  stroke:[0xE6DEA9, 0xE5B047, 0xC5360D]   }, "YlBr5": {classes:5,                  fill:[0xFFFFD4, 0xFED98E, 0xFE9929, 0xD95F0E, 0x993404],                  stroke:[0xE6E6BF, 0xE5C380, 0xE58A25, 0xC35663, 0x8A2F04]     }, etc. Next we create the bucket style.    bucketStyleDef = {       numClasses : colorSeries[colorName].classes, //      classification: 'custom',  //since we are supplying all the buckets //      buckets: theBuckets,       classification: 'logarithmic',  // use a logarithmic scale       styles: theStyles,       gradient:  useGradient? 'linear' : 'off' //      gradient:  useGradient? 'radial' : 'off'     };    theBucketStyle = new OM.style.BucketStyle(bucketStyleDef);    return theBucketStyle; A BucketStyle constructor takes a style definition as input. The style definition specifies the number of buckets (numClasses), a classification scheme (which can be equal-ranged, logarithmic scale, or custom), the styles for each bucket, whether to use a gradient effect, and optionally the buckets (required when using a custom classification scheme). The full source for the demo <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Oracle Maps V2 Thematic Map Demo</title> <script src="http://localhost:8080/mapviewer/jslib/v2/oraclemapsv2.js" type="text/javascript"> </script> <script type="text/javascript"> //var $j = jQuery.noConflict(); var baseURL="http://localhost:8080/mapviewer"; // location of mapviewer OM.gv.proxyEnabled =false; // no mvproxy needed OM.gv.setResourcePath(baseURL+"/jslib/v2/images/"); // location of resources for UI elements like nav panel buttons var map = null; // the client mapviewer object var statesLayer = null, stateCountyLayer = null; // The vector layers for states and counties in a state var layerName="States"; // initial map center and zoom var mapCenterLon = -20000; var mapCenterLat = 1750000; var mapZoom = 2; var mpoint = new OM.geometry.Point(mapCenterLon,mapCenterLat,32775); var currentPalette = null, currentStyle=null; // set an onchange listener for the color palette select list // initialize the map // load and display the states layer $(document).ready( function() { $("#demo-htmlselect").change(function() { var theColorScheme = $(this).val(); useSelectedColorScheme(theColorScheme); }); initMap(); states(); } ); /** * color series from ColorBrewer site (http://colorbrewer2.org/). */ var colorSeries = { //multi-hue color scheme #10 YlBl. "YlBl3": { classes:3, fill: [0xEDF8B1, 0x7FCDBB, 0x2C7FB8], stroke:[0xB5DF9F, 0x72B8A8, 0x2872A6] }, "YlBl5": { classes:5, fill:[0xFFFFCC, 0xA1DAB4, 0x41B6C4, 0x2C7FB8, 0x253494], stroke:[0xE6E6B8, 0x91BCA2, 0x3AA4B0, 0x2872A6, 0x212F85] }, //multi-hue color scheme #11 YlBr. "YlBr3": {classes:3, fill:[0xFFF7BC, 0xFEC44F, 0xD95F0E], stroke:[0xE6DEA9, 0xE5B047, 0xC5360D] }, "YlBr5": {classes:5, fill:[0xFFFFD4, 0xFED98E, 0xFE9929, 0xD95F0E, 0x993404], stroke:[0xE6E6BF, 0xE5C380, 0xE58A25, 0xC35663, 0x8A2F04] }, // single-hue color schemes (blues, greens, greys, oranges, reds, purples) "Purples5": {classes:5, fill:[0xf2f0f7, 0xcbc9e2, 0x9e9ac8, 0x756bb1, 0x54278f], stroke:[0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3] }, "Blues5": {classes:5, fill:[0xEFF3FF, 0xbdd7e7, 0x68aed6, 0x3182bd, 0x18519C], stroke:[0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3] }, "Greens5": {classes:5, fill:[0xedf8e9, 0xbae4b3, 0x74c476, 0x31a354, 0x116d2c], stroke:[0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3] }, "Greys5": {classes:5, fill:[0xf7f7f7, 0xcccccc, 0x969696, 0x636363, 0x454545], stroke:[0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3] }, "Oranges5": {classes:5, fill:[0xfeedde, 0xfdb385, 0xfd8d3c, 0xe6550d, 0xa63603], stroke:[0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3] }, "Reds5": {classes:5, fill:[0xfee5d9, 0xfcae91, 0xfb6a4a, 0xde2d26, 0xa50f15], stroke:[0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3, 0xd3d3d3] } }; function createBucketColorStyle( colorName, colorSeries, rangeName, useGradient) { var theBucketStyle; var bucketStyleDef; var theStyles = []; var theColors = []; var aBucket, aStyle, aColor, aRange; var numClasses ; numClasses = colorSeries[colorName].classes; // create Color Styles for (var i=0; i < numClasses; i++) { theStyles[i] = new OM.style.Color( {fill: colorSeries[colorName].fill[i], stroke:colorSeries[colorName].stroke[i], strokeOpacity: useGradient? 0.25 : 1 }); }; bucketStyleDef = { numClasses : colorSeries[colorName].classes, // classification: 'custom', //since we are supplying all the buckets // buckets: theBuckets, classification: 'logarithmic', // use a logarithmic scale styles: theStyles, gradient: useGradient? 'linear' : 'off' // gradient: useGradient? 'radial' : 'off' }; theBucketStyle = new OM.style.BucketStyle(bucketStyleDef); return theBucketStyle; } function initMap() { //alert("Initialize map view"); // define the map extent and number of zoom levels. // The Universe object is similar to the map tile layer configuration // It defines the map extent, number of zoom levels, and spatial reference system // well-known ones (like web mercator/google/bing or maps.oracle/elocation are predefined // The Universe must be defined when there is no underlying map tile layer. // When there is a map tile layer then that defines the map extent, srid, and zoom levels. var uni= new OM.universe.Universe( { srid : 32775, bounds : new OM.geometry.Rectangle( -3280000, 170000, 2300000, 3200000, 32775), numberOfZoomLevels: 8 }); map = new OM.Map( document.getElementById('map'), { mapviewerURL: baseURL, universe:uni }) ; var navigationPanelBar = new OM.control.NavigationPanelBar(); map.addMapDecoration(navigationPanelBar); } // end initMap function states() { //alert("Load and display states"); layerName = "States"; if(statesLayer) { // states were already visible but the style may have changed // so set the style to the currently selected one var theData = $('#demo-htmlselect').val(); setStyle(theData); } else { // States is a predefined layer in user_sdo_themes var layer2 = new OM.layer.VectorLayer("vLayer2", { def: { type:OM.layer.VectorLayer.TYPE_PREDEFINED, dataSource:"mvdemo", theme:"us_states_bi", url: baseURL, loadOnDemand: false }, boundingTheme:true }); // add drop shadow effect and hover style var shadowFilter = new OM.visualfilter.DropShadow({opacity:0.5, color:"#000000", offset:6, radius:10}); var hoverStyle = new OM.style.Color( {stroke:"#838383", strokeThickness:2}); layer2.setHoverStyle(hoverStyle); layer2.setHoverVisualFilter(shadowFilter); layer2.enableFeatureHover(true); layer2.enableFeatureSelection(false); layer2.setLabelsVisible(true); // override predefined rendering style with programmatic one var theRenderingStyle = createBucketColorStyle('YlBr5', colorSeries, 'States5', true); // specify which attribute is used in determining the bucket (i.e. color) to use for the state // It can be an array because the style could be a chart type (pie/bar) // which requires multiple attribute columns // Use the STATE.TOTPOP column (aka attribute) value here layer2.setRenderingStyle(theRenderingStyle, ["TOTPOP"]); currentPalette = "YlBr5"; var stLayerIdx = map.addLayer(layer2); //alert('State Layer Idx = ' + stLayerIdx); map.setMapCenter(mpoint); map.setMapZoomLevel(mapZoom) ; // display the map map.init() ; statesLayer=layer2; // add rt-click event listener to show counties for the state layer2.addListener(OM.event.MouseEvent.MOUSE_RIGHT_CLICK,stateRtClick); } // end if } // end states function setStyle(styleName) { // alert("Selected Style = " + styleName); // there may be a counties layer also displayed. // that wll have different bucket ranges so create // one style for states and one for counties var newRenderingStyle = null; if (layerName === "States") { if(/3/.test(styleName)) { newRenderingStyle = createBucketColorStyle(styleName, colorSeries, 'States3', false); currentStyle = createBucketColorStyle(styleName, colorSeries, 'Counties3', false); } else { newRenderingStyle = createBucketColorStyle(styleName, colorSeries, 'States5', false); currentStyle = createBucketColorStyle(styleName, colorSeries, 'Counties5', false); } statesLayer.setRenderingStyle(newRenderingStyle, ["TOTPOP"]); if (stateCountyLayer) stateCountyLayer.setRenderingStyle(currentStyle, ["TOTPOP"]); } } // end setStyle function stateRtClick(evt){ var foi = evt.feature; //alert('Rt-Click on State: ' + foi.attributes['_label_'] + // ' with pop ' + foi.attributes['TOTPOP']); // display another layer with counties info // layer may change on each rt-click so create and add each time. var countyByState = null ; // the _label_ attribute of a feature in this case is the state abbreviation // we will use that to query and get the counties for a state var sqlText = "select totpop,geom32775 from counties_32775_moved where state_abrv="+ "'"+foi.getAttributeValue('_label_')+"'"; // alert(sqlText); if (currentStyle === null) currentStyle = createBucketColorStyle('YlBr5', colorSeries, 'Counties5', false); /* try a simple style instead new OM.style.ColorStyle( { stroke: "#B8F4FF", fill: "#18E5F4", fillOpacity:0 } ); */ // remove existing layer if any if(stateCountyLayer) map.removeLayer(stateCountyLayer); countyByState = new OM.layer.VectorLayer("stCountyLayer", {def:{type:OM.layer.VectorLayer.TYPE_JDBC, dataSource:"mvdemo", sql:sqlText, url:baseURL}}); // url:baseURL}, // renderingStyle:currentStyle}); countyByState.setVisible(true); // specify which attribute is used in determining the bucket (i.e. color) to use for the state countyByState.setRenderingStyle(currentStyle, ["TOTPOP"]); var ctLayerIdx = map.addLayer(countyByState); // alert('County Layer Idx = ' + ctLayerIdx); //map.addLayer(countyByState); stateCountyLayer = countyByState; } // end stateRtClick function useSelectedColorScheme(theColorScheme) { if(map) { // code to update renderStyle goes here //alert('will try to change render style'); setStyle(theColorScheme); } else { // do nothing } } </script> </head> <body bgcolor="#b4c5cc" style="height:100%;font-family:Arial,Helvetica,Verdana"> <h3 align="center">State population thematic map </h3> <div id="demo" style="position:absolute; left:68%; top:44px; width:28%; height:100%"> <HR/> <p/> Choose Color Scheme: <select id="demo-htmlselect"> <option value="YlBl3"> YellowBlue3</option> <option value="YlBr3"> YellowBrown3</option> <option value="YlBl5"> YellowBlue5</option> <option value="YlBr5" selected="selected"> YellowBrown5</option> <option value="Blues5"> Blues</option> <option value="Greens5"> Greens</option> <option value="Greys5"> Greys</option> <option value="Oranges5"> Oranges</option> <option value="Purples5"> Purples</option> <option value="Reds5"> Reds</option> </select> <p/> </div> <div id="map" style="position:absolute; left:10px; top:50px; width:65%; height:75%; background-color:#778f99"></div> <div style="position:absolute;top:85%; left:10px;width:98%" class="noprint"> <HR/> <p> Note: This demo uses HTML5 Canvas and requires IE9+, Firefox 10+, or Chrome. No map will show up in IE8 or earlier. </p> </div> </body> </html>

    Read the article

< Previous Page | 98 99 100 101 102 103 104  | Next Page >