Send data from Singleton Class to JSP page - java

I'am developing Struts2 Application. There is a value in database table and I want to use that value in many different Jsp pages. For that I am using singleton class.
DAO Class:
public class TestDAO {
public String getServerName() throws DAOException {
String findStatement = "SELECT name FROM classTest where value='1234';";
PreparedStatement ps=null;
ResultSet rs =null;
try {
ps=DBAccessManager.prepareStatement(findStatement);
rs = ps.executeQuery();
String name = rs.getString("name");
return name;
}catch{ //some text }
}
}
Singleton Class:
public class TestSingleton {
private static TestSingleton INSTANCE;
private String name;
private ServerSingleton() {
try {
setName(new TestDAO().getServerName());
} catch (DAOException e) {
e.printStackTrace();
}
}
public static TestSingleton getINSTANCE() {
return INSTANCE;
}
public static void setINSTANCE(TestSingleton iNSTANCE) {
INSTANCE = iNSTANCE;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
How can I use session in singleton class and read the session in JSP page

In JSP pages you can get the value from the valueStack. Once you get hitted your action to the controller the action context and valueStack are created by the Struts2 filter. You retrieve the value from the database using DAO and store it to the valueSrack. Note, that the valueStack is available not only in the controller but also in the view referencing a JSP page. In Struts2 the controller itself is exposed to the view via OGNL or EL. It is set on top of the valueStack.
So any changes to properties of the controller are reflected to JSP returned as a result with dispatcher result type which is default. If you use many JSP pages in many results then you have to retrieve the value from the database each time the request is made. Then you set the value to the property of controller.
Thus it is available to JSP returned as a result to the view via OGNL. All struts tags are supported to use OGNL in their attributes where you can write OGNL expressions or use EL.
It doesn't matter how you set the properties of the controller by the singleton object or prototype oblect the value is evaluated by OGNL expression. For it to work you provide your oblects with accessors and don't use a static context. Because the static context is turned off by default Struts2 configuration.
However if the objects are evaluated by many requests the singleton objects are shared by different threads and should be thread-safe.
If you use a session object which is implemented as a map in Struts2 and instance is already sinchronized. So you have only referencing a session scoped objects from the map which is available in the action context.

Related

Dynamic per REST(Jersey) request binding of configurations in Guice

We are using Guice in our project for DI. Currently we have some configurations(properties) that we load a t server startup from a file. These are then bound to all the components & used for all the requests.
But now, we have multiple property files & load them at startup. These configurations can be different per REST(Jersey) request as they depend on the input.
So, we need to bind these configurations dynamically for each request. I looked into Guice API for #RequestScoped, but did not find anything specificallyu helpful.
There are few questions similar to this, but no luck yet. Can you please help me with this.
I'm providing 2 ways of doing this and both are request scoped.
Using HttpServletRequest, for classes where you can Inject request object.
Using ThreadLocal, Generic way. It can be used in any class.
(NOTE: This method wouldn't work if your creating new threads in your code and want to access the value. In which case you'll have to pass the values through Objects to those threads)
I meant something like this:
public class RequestFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
List listOfConfig = //load Config;
request.setAttribute("LOADED_CONFIG",listOfConfig);
// If you want to access this value at some place where Request object cannot be injected (like in service layers, etc.) Then use below ThreadLocals.
ThreadLocalWrapper.getInstance().get().add("adbc"); // In general add your config here, instead of abdc.
}
}
My ThreadLocalWrapper looks like this:
public class ThreadLocalWrapper {
private static ThreadLocal<List<String>> listOfStringLocals; // You can modify this to a list of Object or an Object by itself.
public static synchronized ThreadLocal<List<String>> getInstance() {
if (listOfStringLocals == null) {
listOfStringLocals = new ThreadLocal<List<String>>() {
#Override
protected List<String> initialValue() {
return new ArrayList<String>();
}
};
}
return listOfStringLocals;
}
}
To Access the value:
In Controller - Inject HttpServletRequest Object and do getAttribute() to get the value. Since HttpServletRequest Object is requestScoped, you can set the loaded config. into this and access it in your controller's using request Object again.
In Any other part of the code - If HttpServletRequest is not available then you can always use the ThreadLocal example shown. To access this value.
public class GuiceTransactionImpl implements GuiceTransaction {
private String value = "";
public GuiceTransactionImpl(String text) {
value = text;
}
#Override
public String returnSuccess() {
return value + " Thread Local Value " + ThreadLocalWrapper.getInstance().get();
}
}

JSP-EL session variable access error: javax.el.PropertyNotFoundException despite said property being public

I am trying to create a simple DB web application using MySQL, JDBC, Netbeans.
I have the following code in a .jsp page
<c:if ${sessionScope.Staff.getStatus() == sessionScope.Staff.financial_staff_status} >
Financial staff
</c:if>
where sessionScope.Staff contains an object of Staff Data type:
public class StaffData
{
//constants
public final byte default_staff_status = 0;
public final byte financial_staff_status = 1;
public final byte legal_staff_status = 2;
public final byte secretarial_staff_status = 3;
//other data
StaffData()
{
//initializations
}
void authenticate(int staff_num, String passwd) throws ClassNotFoundException, SQLException
{
//connect to sever, blah, blah
}
public String getName()
{
return this.name;
}
public int getNumber()
{
return this.staff_number;
}
public byte getStatus()
{
return this.status;
}
}
I am setting the session object in advance:
request.getSession().setAttribute("Staff", currentStaff);
I am getting the following error:
javax.el.PropertyNotFoundException: Property 'financial_staff_status' not found on type staff.StaffData
In the staff data object in the session, public methods such as getName() can be accessed, but public members such as financial_staff_status cannot.
Why am I getting this problem? The problem seems to be with the final variables. Non final variables can easily be accessed without a problem.
You actually have three problems with the EL expression:
<c:if ${sessionScope.Staff.getStatus() == sessionScope.Staff.financial_staff_status} >
The conditional expression to be evaluated should be within the mandatory test attribute
The property status should be accessed as Staff.status as it already has a public getter method
The property financial_staff_status requires a public getter method in class StaffData. EL is strict with javabeans compliance of object classes and how properties are accessed (must be via a public getter)
Additionally, its not strictly necessary to qualify the scope of an attribute, unless you have multiple attributes with the same name in different scopes or wish to be explicit for clarity. The different scopes will be searched starting with the narrowest (pageScope) through to the widest (applicationScope).
Having added the public getter for the financial_staff_status property to your class, the expression should be:
<c:if test="${sessionScope.Staff.status == sessionScope.Staff.financial_staff_status}">
or simply:
<c:if test="${Staff.status == Staff.financial_staff_status}">

Maintaining values of action variables?

class SampleAction extends ActionSupport {
private Map<String,String> circleIdNameMap;
public String preprocess(){
--logic for populating value of MAP
}
--getters and setters
}
Now my problem is on page load I call preprocess function and populate the value of Map. After page submit another method is called and during that after some DB interaction it redirects to JSP, but this time the value of Map is empty. I am using this Map for drop-down tag in Struts2.
My preprocess is associated in the link like:
href="/gma/preprocessConfigureTspThreshold?operatorId=5102&sessionId=12332"‌`​
So only first time when the link is clicked preprocess is called, after that when I redirect to my JSP so its not called then, so second time the value of Map is empty.
Shall I put the map in a session so that it is retained? Or can do something else?
I read that don't use preprocess function, use Preparable interface. But as per docs:
The prepare method will always be called by the Struts 2 framework's prepare interceptor
whenever any method is called for the Action class.
So, it will be called for every method. I want preprocess to be called only when page loads.
The prepare method of the Preparable action class is called on every action execution, that's right. That might be the reason why you prepare the map for a drop-down in the preprocess method.
public class SampleAction extends ActionSupport {
private Map<String,String> circleIdNameMap;
private String circleId;
//getters and setters here
protected boolean reload = false;
private void preprocess(){
// Get the Map by calling a stateless Session bean
circleIdNameMap = remoteInterface.getMap();
}
public String action1(){
preprocess();
Map session = ActionContext.getContext().getSession();
session.put("circleIdNameMap ", circleIdNameMap );
return SUCCESS;
}
public String action2(){
Map session = ActionContext.getContext().getSession();
circleIdNameMap = (Map<String,String>)session.get("circleIdNameMap");
if (circleIdNameMap == null){
if (reload) {
preprocess();
Map session = ActionContext.getContext().getSession();
session.put("circleIdNameMap ", circleIdNameMap );
} else {
addActionError("circleIdNameMap is null");
return ERROR;
}
}
return SUCCESS;
}
...//other actions
}
the JSP for drop-down
<s:select name="circleId" list="circleIdNameMap" listKey="key" listValue="value"/>
The meaning of this code is: you should not return result SUCCESS or INPUT if fields in JSP aren't initialized.

Spring 3 MVC Default view for spring controller

I have a simple question, but I cannot find a solution anywhere.
For a project I have a controller which pulls lists according to some business rules. I have multiple RequestMappings and multiple methods but they should all return the same view. Is there a way to specify a default view for a controller?
Currently my code looks like this:
#Controller
public class OverviewController {
#RequestMapping("/{name}-games")
public String getOverview(#PathVariable("name") String name) {
// Code
return "view";
}
#RequestMapping("/{category}")
public String getCategory(#PathVariable("category") String category) {
// Code
return "view";
}
#RequestMapping("/special-{promo}-games")
public String getSpecialPromo(#PathVariable("promo") String namepromo) {
// Code
return "view";
}
}
I can replace the return "view"; with something like return view(); everywhere but I am hoping to find something more like an annotation:
#DefaultView()
public String view() {
return "view";
}
I am unable to find any such thing in the spring documentation. Is this possible or is the whole setup wrong to start with?
According to the Sping Reference,
The RequestToViewNameTranslator interface determines a logical View name when no such logical view name is explicitly supplied.
(That is when your controller method returns Model, Map or void.)
You could implement this interface, but I think in your example the best thing you can do is defining a constant as CodeChimp has suggested.
Can you not go with the approach of having multiple view resolvers using order??
Have the beanNameViewResolver with order 0,which tries to map the matching bean to the modelAndView(common for controller in your case) that you return.
In case it doesnt match then you can default it onto a internalResourceViewResolver(order=1) to provide default behaviour .
Your default view page required some attributes that should be send via Model Attributes.Assuming,these required model attributes are same in all your methods of different Business logic.You can add them in Flash attributes and redirect to default Method.
Suppose X1,X2 attributes are same in all Handler method independent of Logic
#Controller
#SessionAttribute({"X1","X2"})
public class OverviewController {
#RequestMapping("/{name}-games")
public String getOverview(#PathVariable("name") String name,final RedirectAttributes redirectAttributes) {
// Code
//add attributes requires for view in Flash attribute
redirectAttributes.addFlashAttribute("X1", "X1");
redirectAttributes.addFlashAttribute("X2", "X2");
return "redirect:defaultview";
}
#RequestMapping("/{category}")
public String getCategory(#PathVariable("category") String category,final RedirectAttributes redirectAttributes) {
// Code
//add attributes requires for view in Flash attribute
redirectAttributes.addFlashAttribute("X1", "X1");
redirectAttributes.addFlashAttribute("X2", "X2");
return "redirect:defaultview";
}
#RequestMapping("/special-{promo}-games")
public String getSpecialPromo(#PathVariable("promo") String namepromo,final RedirectAttributes redirectAttributes) {
// Code
//add attributes requires for view in Flash attribute
redirectAttributes.addFlashAttribute("X1", "X1");
redirectAttributes.addFlashAttribute("X2", "X2");
return "redirect:defaultview";
}
#RequestMapping("defaultview")
public String default(Model model) {
//here you can access all attributes in Flash Map via Model Attribute
// Code
model.addAttribute("X1","X1");
model.addAttribute("X1","X1");
return "view";
}
}
Caution:you have to add requires attributes in Session also because if you refresh page ,this avoids well known Exception.
Thank you

java connection class, passing string from servlet

I am developing a web application using JSP and Servlets.(Database: Oracle10, Container: Glassfish).
I have developed A Class for creating connection.
(Conn.java):
public class Conn
{
private Connection con = null;
public Connection getCon()
{
String home = System.getProperty("user.home");
home = home+"\\dbFile.properties";
//Read properties of Connection String from that file and Create Connection
return con;
}
}
Then I have a 4 other classes for SELECT, INSERT, UPDATE, DELETE transactions which are using above Conn.java class for getting connection:
(Select.java)
public class Select
{
private Conn connection = new Conn();
private Connection con = null;
private PreparedStatement pstmt = null;
private ResultSet rs=null;
public String[][] selectData(String query)
{
String[][] data=null;
if(con==null)
{
con = connection.getCon();
}
//execute query put data in two dimensional array and then return it
return data;
}
}
INSERT, UPDATE and DELETE are coded similar way as above Select.java is coded.
So in all servlets I am just using those 4(SELECT, INSERT, UPDATE, DELETE) classes, passing query to them and getting the result.
Sample Servlet
public class SampleServ extends HttpServlet
{
Select select = new Select();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String data[][];
data = select.selectData(QUERY_GOES_HERE);
//AND OTHER CODE
}
}
It works perfectly, but now our requirement is to change Database String after user is login. So I want to pass the User specific property file name to the Conn.java class. So for that I am storing the property file name in cookie.
I have think one way of doing this:
Get the cookie value in all servlets
Pass the cookie value to the selectData() method of Select.java class And from that class
pass the cookie value to the getConn() method of Conn.java class
So I want know if there is any better way to pass this Connection String file name to Conn.java class?
Thanks in advance.
HttpSession is where user info should be stored (with some concerns).
In your case, where you seem to have many different web applications, each of them will have a different session, and you will need to update all of them.
I prefer another approach (and this is a personal opinion, which can be discussed) which is based in the ThreadLocal class.
You can write a servlet filter, that will
read the cookie value
store it in a ThreadLocal
after the filter.doFilter method, you will have to clean it (This is extremely important, so you don't the have the chance of mixing sessions), just put the clean method in a finally block so it gets executed whatever happens.
The main advantage of this approach is that you may not have access to the HttpSession or HttpServletRequest, and you will still be able to get the value in the ThreadLocal.
An example of a ThreadLocal container you can use is this one :
public class ThreadLocalContainer {
private static ThreadLocal<String> userId=new ThreadLocal<String>();
public static String getUserId(){
return userId.get();
}
public static void setUserId(String uid){
userId.set(uid);
}
public static void resetUserId(){
userId.remove();
}
}
then you will be able to access the userId just by calling ThreadLocalContainer.getUserId() everywhere in your code, even if you don¡t have access to the http context.
Make sure you define the servlet filter in all your webapps, so the userId gets properly set.

Categories