java web frameworks

Sunday, October 4, 2009

jess telnet wrapper?

Multi users can telnet to jess working memory after authentication.
yet while calling(exit) for one user , all user breaks out.


package org.jesstools.telnetforjess;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import jess.*;

public class TelnetJessThread implements Runnable{

final static int port = 1222;
SocketHandler scktHandler = null;
static Main main=null;
static Rete rt = null;

public TelnetJessThread(SocketHandler scktHandler){
this.scktHandler=scktHandler;
}
public static void main(String[] args) {
try {
main = new Main();
rt = new Rete();
ServerSocket ssckt= new ServerSocket(port);
while(true){
Socket s1 = ssckt.accept();
Thread tjs= new Thread(new TelnetJessThread(new SocketHandler(s1)));
tjs.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}

public void run(){
try {
System.out.println("oh1");

rt.addOutputRouter("t", scktHandler.jpw);
rt.addInputRouter("t", scktHandler.jpr, true);
rt.addInputRouter("WSTDIN", scktHandler.jpr, true);
rt.addOutputRouter("WSTDOUT", scktHandler.jpw);
rt.addOutputRouter("WSTDERR", scktHandler.jpw);
main.initialize(new String[0], rt);
main.execute(main.getM_filename() == null);

Thread.sleep(1234);

} catch (Exception e) {
e.printStackTrace();
}

}
}







package org.jesstools.telnetforjess;

import java.net.*;
import java.io.*;

public class SocketHandler {
Socket sckt=null;
String user=null;
JessPipedReader jpr=null;
JessPipedWriter jpw=null;
public boolean loggedIn=false;

public SocketHandler(Socket sckt){
try {
this.sckt=sckt;
jpr=new JessPipedReader(sckt.getInputStream());
jpw=new JessPipedWriter(sckt.getOutputStream());
jpr.sckthndlr=this;
if(!loggedIn)
login();
} catch (IOException e) {
e.printStackTrace();
}
}

private void login() {
try{
while(!loggedIn){
jpw.write(" \n");
jpw.flush();
jpw.write("Login: ");
jpw.flush();
String login=readLine();
System.out.println("login="+login);
jpw.write("Password: ");
jpw.flush();
String password=readLine();
//System.out.println("password="+password);
if(authenticate(login, password)){
System.out.println("loggedIn: "+login);
loggedIn=true;
}
}
}catch(Exception e){
e.printStackTrace();
}

}

private String readLine(){
try{
char c=' ';StringBuffer _str=new StringBuffer();
while((c=(char)jpr.read())!= '\n' )
_str.append(c);
return _str.substring(0, _str.length()-1);
}catch(Exception e){
e.printStackTrace();
}
return "";

}

private boolean authenticate(String username, String passwd){
if("user1".equals(username) && "passwd1".equals(passwd))
return true;
else
return false;
}
}




JessPipedReader and JessPipedWriter are 2 extra classes that extend InputStreamReader and OutputStreamWriter.. overrode close() method to not call super.close(). still its closing!!! why??

Tuesday, August 25, 2009

PSSServlet codebase


package org.pss;

import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

import ognl.*;


public abstract class PSSServlet extends HttpServlet implements SingleThreadModel{

private MarkupWriter markupWriter= new MarkupWriter(this.getClass(),this);



protected void doPost(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException{
markupWriter.setReqRespContext(req, resp,getServletContext());
render(req, resp,null);
PrintWriter pw=resp.getWriter();
pw.print(markupWriter.refreshMarkupsAsString());
pw.flush();
}

protected void doGet(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException{
markupWriter.setReqRespContext(req, resp,getServletContext());
render(req, resp,null);
PrintWriter pw=resp.getWriter();
pw.print(markupWriter.refreshMarkupsAsString());
pw.flush();
}

protected void loadFieldsFromSession(javax.servlet.http.HttpServletRequest req){
try {
PSSSession thisObjSession=(PSSSession)req.getSession().getAttribute(this.getClass().getName());
Hashtable table=thisObjSession.getSessionMap();
Set keys=table.keySet();
for(String key: keys){
Object val=table.get(key);
try {
Ognl.setValue(key, this,val);
} catch (Exception e) {
e.printStackTrace();
}

}
} catch (Exception e) {
e.printStackTrace();
}
}

protected String refreshMarkup(){
return markupWriter.refreshMarkupsAsString();
}


public MarkupWriter getMarkupWriter(){
return markupWriter;
}

protected abstract void render(HttpServletRequest req, HttpServletResponse resp, Object obj) throws javax.servlet.ServletException, java.io.IOException;


}









package org.pss;

import java.util.*;
import java.io.*;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ognl.*;

public class MarkupWriter {
Class clss=null;
Object servletObj=null;
HttpServletRequest req=null;
HttpServletResponse resp=null;

public void setReqRespContext(HttpServletRequest request,HttpServletResponse response,ServletContext ctx){
req=request;
resp=response;
//context=ctx;
}

boolean populateInitialMarkupCalled=false;
public boolean skipEvaluationOfMarkup=false;


HashMap chunkMap= new HashMap();
HashMap owcidMap= new HashMap();
HashMap pwcidMap= new HashMap();
TreeMap populatedChunkMap= new TreeMap();
HashMap populatedOwcidMap= new HashMap();
HashMap populatedPwcidMap= new HashMap();

public MarkupWriter(Class clas){
System.out.println("here 2 -- "+clas.getName());
clss=clas;
}
public MarkupWriter(Class clas, Object obj){
System.out.println("here 3-- "+clas.getName()+":"+obj);
clss=clas;
servletObj=obj;
}
public MarkupWriter(Class clas, Object obj,HttpServletRequest request, HttpServletResponse response){
System.out.println("here 3-- "+clas.getName()+":"+obj);
clss=clas;
servletObj=obj;
req=request;
resp=response;
}

public MarkupWriter(){
super();
System.out.println("here 1-- ");
}

public HashMap getChunkMap(){
return chunkMap;
}

public TreeMap getPopulatedChunkMap(){
return populatedChunkMap;
}


/**
* refresh entire populated markup (after recursively travelling nested components)
*/
public String refreshMarkupsAsString(){
if(!populateInitialMarkupCalled){
populateInitialMarkup();
populateInitialMarkupCalled=true;
}
if(!skipEvaluationOfMarkup){
evaluatePwcidMarkup();
evaluateOwcidMarkup();
}
Collection chunkVals=populatedChunkMap.values();
StringBuffer sb= new StringBuffer("");
for(String str: chunkVals){
sb.append(str);
}
return sb.toString();
}

private void evaluatePwcidMarkup(){
Set pwcidKeys=pwcidMap.keySet();
for(Integer key: pwcidKeys){
String val=pwcidMap.get(key);
String populatedVal="";
try {
populatedVal= Ognl.getValue(val, servletObj).toString();
} catch (OgnlException e) {
e.printStackTrace();
}
populatedChunkMap.put(key, populatedVal);
populatedPwcidMap.put(key, populatedVal);
}
}

/**
* owcid has format :.
* expr evaluates to servletObj and evaluates to argument.
* This recursively travels internal components.
*/
private void evaluateOwcidMarkup(){ // this method could have been combined with evaluatePwcidMarkup
Set owcidKeys=owcidMap.keySet();
for(Integer key: owcidKeys){
String val=owcidMap.get(key);
String prefixExpr=val.substring(0,val.indexOf(":"));
String suffixExpr2=val.substring(val.indexOf(":")+1);
Object populatedPrefixVal=null;
Object populatedSuffixVal2=null;
String resultVal="";
try {
populatedPrefixVal=Ognl.getValue(prefixExpr, servletObj);
try {
populatedSuffixVal2=Ognl.getValue(suffixExpr2, servletObj);
} catch (Exception e) {
e.printStackTrace();
}
if(populatedPrefixVal instanceof PSSServlet){
PSSServlet servlet=((PSSServlet)populatedPrefixVal);
servlet.render(req, resp, populatedSuffixVal2);
resultVal=servlet.refreshMarkup();
}
if(populatedPrefixVal instanceof PSSComponent){
PSSComponent servlet=((PSSComponent)populatedPrefixVal);
servlet.render(req, resp, populatedSuffixVal2);
resultVal=servlet.refreshMarkup();
}
} catch (Exception e) {
e.printStackTrace();
}
populatedChunkMap.put(key, resultVal);
populatedOwcidMap.put(key, resultVal);
}
}

public boolean populateInitialMarkup(){
try{
populateInitialMarkupCalled=true;
String fileName="/"+clss.getName().replace(".", "/")+".html";
System.out.println("clss.getName()="+fileName);
String fileStr=readFile(fileName);

ArrayList chunks=getChunks(fileStr);
int i=0;
for(String st:chunks){
i++;
if(st.startsWith("${owcid:")){
populatedChunkMap.put(i,st);
chunkMap.put(i,st);
owcidMap.put(i,st.substring(8).trim());
}
else if(st.startsWith("${pwcid:")){
populatedChunkMap.put(i,st);
chunkMap.put(i,st);
pwcidMap.put(i,st.substring(8).trim());
}else{
populatedChunkMap.put(i,st);
chunkMap.put(i,st);
}
}
}catch(Exception e){
e.printStackTrace();
}

return true;
}


private String readFile(String fileName){
try{
System.out.println(this.getClass().getResource(fileName));

Reader is=new InputStreamReader(this.getClass().getResourceAsStream(fileName));

char[] barr= new char[4096];
int i=0;
StringBuffer sb= new StringBuffer("");
while((i=is.read(barr))>=0)
sb.append(barr,0,i);
return sb.toString();
}catch(Exception e){
e.printStackTrace();
}
return null;
}

/**
* chunks - a concept I read in book- "tapestry in action"
*/
private ArrayList getChunks(String str){
int currIdx=0,endIndx=0,_endIndxP=0,_endIndxO=0,prevIdx=0;
ArrayList alist=new ArrayList();
while(true){
_endIndxP=str.indexOf("${pwcid:",currIdx);
_endIndxO=str.indexOf("${owcid:",currIdx);
if(_endIndxP<0 && _endIndxO<0){
alist.add(str.substring(currIdx));
break; //over
}else if((_endIndxO<0 || _endIndxP<_endIndxO) && _endIndxP>= currIdx){
endIndx=_endIndxP;
}else if((_endIndxP<0 || _endIndxO<_endIndxP) && _endIndxO>= currIdx){
endIndx=_endIndxO;
}else {
throw new RuntimeException("!ERROR: invalid condition "+endIndx);
}

int _tmpIdx=str.indexOf("}",endIndx);
if(_tmpIdx>endIndx){
alist.add(str.substring(currIdx,endIndx));
alist.add(str.substring(endIndx,_tmpIdx));//pwcid/owcid
currIdx=_tmpIdx+1;
}else{//no closing braces
throw new RuntimeException("No closing braces for ${pwcid/owcid: "+endIndx);
}

}
return alist;
}
}








package org.pss;

import java.util.*;
/**
* contains one hashtable storing key value being ognl expression.
* @author hari sujathan
*
*/

public class PSSSession {
private Hashtable sessionMap= new Hashtable();

public Hashtable getSessionMap() {
return sessionMap;
}

public void setSessionMap(Hashtable sessionMap) {
this.sessionMap = sessionMap;
}

}

PSSServlet- mimics component oriented frameworks

PSSServlet (Mimicing Component oriented frameworks)


There are many component oriented java web frameworks, as well as request oriented frameworks as well which existed from starting of servlets.

Component oriented frameworks try to mimic desktop like environment by trying to detach entire User objects from complexities of HTTPServletRequest plumbing. This is not yet a theoritically proven concept as there are still limitations to it.


Component Oriented Pipeline


Request Based Pipeline



In request based frameworks like SpringMVC(powerful), struts the User objects have complete access to HTTP Servlet request objects. While the fundamental complication that component based frameworks enter into is – “they detach request from end user objects”. This concept has too much impact. Once user has no access to fine grained control over response generated, too much magic is done by component based framework. This include generation of unique ids for each detached user object properties inside the HTML so that they can be uniquely tracked within the server, when next request hits server. This will create big problem if similar userId is generated across pages and some javascript submits requests across pages. Javascripting becomes a nightmare. There is a need to synchronize javascript events with server component events(?)..

Arbitary change of DOM model and its handling in server should be carefully done in component based frameworks. In an HTML, it may not be just that form submissions/javascript interactions happen only with one Page. All possible combinations of dynamic form creation/subission to multiple pages dynamically have to be considered.


It often ends up that the end user has to know internals of these component based frameworks like tapestry, wicket, JSF very well before using any of these frameworks. For that matter JSF is simplistic, and easier to learn. You just normally create a new FacesContext object and loop through various JSF phases on top of FacesContext which you can access from anywhere.


Request based frameworks:

HTTPServletRequest based objects are fully accessible in request based frameworks. This allow full finegrained control of logic that can happen when requests come and go back. Struts- mvc-frontcontroller pattern allowed good seperation of logic. Spring MVC is even more powerful allowing multiple controllers and many other features. Still the amount of services that these frameworks provides is fixed.

Question comes: why can't users extend to add/redistribute more services which these servlets can use. Possibility of expansion of request based framework is very large as in PSSServlet.

This is just a concept trying to mimic tapestry/wicket like HTML templating mechanism with just 3 java files. Its like JSP's <%= %> as well as “jsp:include” . Just the fact that JSP cannot be extended easily, make this sort of PSSServlet needed. Writing new frameworks similar to struts, involves more coding by extending upon JSP codebase.

Why not just stick to servlets alone which is bare minimum and extend on that by providing a cloud of services which user can invoke in a pipelined manner to minimize coding.



PSSServlet

It has 4 java files as of release 0.5.0.0 (1 days coding effort). Actually just 2 java files: MarkupWriter and PSSServlet. PSSComponent is copy-paste of PSSServlet, and PSSSession is having just one hashtable. PSSServlet has dependency on 2 external jars:ognl and javassist for expression evaluation.

Features(as of now it follows SingleThreadedModel):

  1. for each Servlet, it auto renders corresponding HTML template similar to JSP.

  2. Takes property markup and renders property populated in servlet at appropriate time/phase as what user decides(no one phase like JSP)

  3. the markup is maintained in chunks(concept from book- tapestry in action), and can be dynamically overwritten in appropriate phase

  4. owcid/pwcid. owcid- refers to object web-component id(a sub template/seperate web component). pwcid is just a property id within servlet. Usage- ${owcid:<component-name>:<argument-param>} . ${pwcid:<property-ognl-expression>}

  5. rendering of subcomponents order can be fine controlled and even the order. Populating from session should happen at what phase is also controlled

  6. Full access to HttpServletRequest, HttpServletResponse object throughout.



Final Say:

So many frameworks might have come about because of improper design of JSP(just trying to mimic ASP). Time to improve on JSP itself, and provide more concrete servlet based frameworks which has huge flexibility and efficiency.

Tuesday, August 4, 2009

hundreds of web frameworks to come

There are say currently around 50+ popular java web frameworks (java-source.net, java-opensource.com).
Which one is the best is a question that is very difficult to answer.

Followers

About Me