GSON, #SerializedName not taken into account when class is loaded in different scope - scope

I have created two exactly the same classes in two different packages and two different .jars. the com.test is loaded globally (placed in /lib/ext/) in Tomcat7, while es.package is loaded as a dependency of a portlet.
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class RequestBean implements Serializable {
#SerializedName("SOMETHING")
private String id;
#SerializedName("CUENTA")
private String account;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
When having the following code in the portlet:
com.test.RequestBean localBean = new com.test.RequestBean();
localBean.setAccount("account");
localBean.setId("100");
es.package.RequestBean globalBean = new es.package.RequestBean();
globalBean.setAccount("account");
globalBean.setId("100");
System.out.println(gson.toJson(localBean, localBean.getClass()).toString());
System.out.println(gson.toJson(globalBean, globalBean.getClass()).toString());
To my surprise, the result is different. For the globalBean #SerializedName is not taken into account. What can be the reason that? Global class is available in the global scope and the local one only for the scope of a portlet.
{"SOMETHING":"100","CUENTA":"account"}
{"id":"100","account":"account"}

The reason was gson-2.2.0 loaded in the scope of portlet and gson-3.2.1 in the global. Leaving just the global one fixed this issue.

Related

Send Object between #ViewScoped beans

I managed to create very simple example of sending Object between JSF pages:
First page:
#Named
#ViewScoped
public class Pricing
{
public Pricing()
{
int ww = 3;
PricingFormData obj = new PricingFormData(334, "Lalalala");
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("yourKey", obj);
}
Second page:
#Named
#ViewScoped
public class PricingCalculator implements Serializable
{
PricingFormData get;
public PricingCalculator()
{
get = (PricingFormData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("yourKey");
}
}
Custom Object:
public class PricingFormData
{
private int id;
private String name;
public PricingFormData(int id, String name)
{
this.id = id;
this.name = name;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
This code works but I have several questions which I want to ask:
The code is working in View scope. What will happen if multiple users are clicking on the pages? Are these Objects are going to be mixed? Do I need to use some unique ID for Object key for example session ID. But here I don't have session.
What will happen if the Objects are too many(multiple users are working on the web site)? When the objects will be disposed?

How do I access a derived class value from a base class static method?

Here is a sample of what I am trying to accomplish:
public class BaseClass<T>
{
public static T GetByID(int ID)
{
// Need database name here that is determined at design time in the derived class.
var databaseName = "";
// do some stuff involving database name that gets me object by ID here.
return default(T);
}
}
public class DerivedClass : BaseClass<DerivedClass>
{
private string DatabaseName { get; set; }
}
Basically, how would I access the derived "DatabaseName" in the base class static GetByID method?
EDIT: After I posted this, I tried one more thing. I played with attributes earlier, and failed, but I think my brain was mushy. Just tried again and ran a test, and it is working. Here is the updated sample.
public class BaseClass<T>
{
public static T GetByID(int ID)
{
// Need database name here that is determined at design time in the derived class.
var databaseName = ((DatabaseAttribute)typeof(T).GetCustomAttributes(typeof(DatabaseAttribute), true).First()).DatabaseName;
// do some stuff involving database name that gets me object by ID here.
return default(T);
}
}
[Database("MyDatabase")]
public class DerivedClass : BaseClass<DerivedClass>
{
}
public class DatabaseAttribute : Attribute
{
public DatabaseAttribute(string databaseName)
{
DatabaseName = databaseName;
}
public string DatabaseName { get; set; }
}
Base class to derived class is a one-way inheritance: The base class has no knowledge of the existance of a derived class, and so it can't access it.
In addition to that you will have a hard time accessing a non-static property from a static method.
I know you've already answered your own question, but some improvements....
Add a where clause to guarantee inheritance, it means any static methods can make use of inherited methods. You might also want to add the new() clause if you wish to be able to create instances of the inherited class.
public class BaseClass<T> : where T : BaseClass<T>
{
static readonly string databaseName;
static BaseClass() {
// Setup database name once per type of T by putting the initialization in
// the static constructor
databaseName = typeof(T).GetCustomAttributes(typeof(DatabaseAttribute),true)
.OfType<DatabaseAttribute>()
.Select(x => x.Name)
.FirstOrDefault();
}
public static T GetByID(int ID)
{
// Database name will be in the static field databaseName, which is unique
// to each type of T
// do some stuff involving database name that gets me object by ID here.
return default(T);
}
}
[Database("MyDatabase")]
public class DerivedClass : BaseClass<DerivedClass>
{
}
public class DatabaseAttribute : Attribute
{
public DatabaseAttribute(string databaseName)
{
DatabaseName = databaseName;
}
public string DatabaseName { get; set; }
}

Enum-Like object which contains properties

I am trying to figure out a way to have a class full of static objects which each can have a variety of static properties.
I want to be able to pass these properties around and even set them as static properties of other object and I also want to be able to switch through the objects.
Here is an example illustrating what I mean:
Creating and Sending a Message
class Program
{
static void Main(string[] args)
{
MarketOrder Order = new MarketOrder("DELL", MessageProperties.SecurityType.Equity, MessageProperties.ExchangeDestination.ARCA.PostOnly);
SendOrder(Order);
Console.ReadLine();
}
public static void SendOrder(MarketOrder Order)
{
switch (Order.SecurityType)
{
case MessageProperties.SecurityType.Equity:
// Equity sending logic here
break;
case MessageProperties.SecurityType.Option:
// Option sending logic here
break;
case MessageProperties.SecurityType.Future:
// Future sending logic here
break;
}
}
}
This does not want to compile because it won't let me switch the Order.SecurityType object.
MarketOrder Class
public class MarketOrder
{
public readonly string Symbol;
public readonly MessageProperties.SecurityType SecurityType;
public readonly MessageProperties.ExchangeDestination ExchangeDestination;
public MarketOrder(string Symbol, MessageProperties.SecurityType SecurityType, MessageProperties.ExchangeDestination ExchangeDestination)
{
this.Symbol = Symbol;
this.SecurityType = SecurityType;
this.ExchangeDestination = ExchangeDestination;
}
}
MessageProperties Class
public abstract class MessageProperties
{
public class ExchangeDestination
{
public readonly string Value;
public readonly double ExchangeFee;
public ExchangeDestination(string Value, double ExchangeFeed)
{
this.Value = Value;
this.ExchangeFee = ExchangeFee;
}
public abstract class ARCA
{
public static ExchangeDestination Only = new ExchangeDestination("ARCA.ONLY", 0.01);
public static ExchangeDestination PostOnly = new ExchangeDestination("ARCA.ONLYP", 0.02);
}
public abstract class NYSE
{
public static ExchangeDestination Only = new ExchangeDestination("NYSE.ONLY", 0.01);
public static ExchangeDestination PostOnly = new ExchangeDestination("NYSE.ONLYP", 0.03);
}
}
public class SecurityType
{
public readonly string Value;
public SecurityType(string Value)
{
this.Value = Value;
}
public static SecurityType Equity = new SecurityType("EQ");
public static SecurityType Option = new SecurityType("OPT");
public static SecurityType Future = new SecurityType("FUT");
}
}
Enums work perfectly for what I am trying to do except it is hard to have multiple properties of an enum value. I considered using Attributes on Enums to set the properties but getting those vs. getting static properties of objects is substantially slower and my application is extremely speed/latency sensitive.
Is there perhaps a better way of accomplishing what I am trying to do?
Thanks in advance for your help!
William

JSF - Get the SessionScoped Bean instance

I have this configuration on my web application. 2 beans :
1° Bean - It checks the login;
#ManagedBean(name="login")
#SessionScoped
public class Login {
private String nickname;
private String password;
private boolean isLogged;
public String getNickname() { return nickname; }
public void setNickname(String newValue) { nickname=newValue; }
public String getPassword() { return password; }
public void setPassword(String newValue) { password=newValue; }
public void checkLogin() {
... i check on db the nickname and the password ...
if(USER EXIST) {
isLogged=true;
} else {
isLogged=false;
}
return true;
}
}
2° Bean - Manage User parameter :
#ManagedBean(name="user")
#SessionScoped
public class User {
private String name;
private String surname;
private String mail;
public User() {
String[] record=null;
Database mydb=Configuration.getDatabase();
mydb.connetti();
ArrayList<String[]> db_result=null;
db_result=mydb.selectQuery("SELECT name, surname, mail, domicilio FROM users WHERE nickname='???????'");
int i = 0;
while (i<db_result.size() ) {
record=(String[]) db_result.get(i);
i++;
}
}
... getter and setter methods...
}
As you can see, I would like to know how get the nickname setted previously on my login bean, so i can do the query on my DB.
In fact i need to get the instance of the current-session bean login : how can I get it? I should use somethings like session.getBean("login") :)
Hope this question is clear :)
Use #ManagedProperty to inject it and use #PostConstruct to access it after bean's construction (because in a normal constructor it would be still null).
#ManagedBean
#SessionScoped
public class User {
#ManagedProperty(value="#{login}")
private Login login;
#PostConstruct
public void init() {
// Put original constructor code here.
}
// Add/generate getters/setters and other boilerplate.
}
That said, this is not the correct approach. You'd like to do it the other way round. Inject User in Login by #ManagedProperty(value="#{user}") and do the job during submit action method.
You'd also like to put the password in WHERE clause as well. There's absolutely no need to haul the entire users table into Java's memory and determine it one by one. Just let the DB do the job and check if it returns zero or one row.
Also try using the following code:
ExternalContext tmpEC;
Map sMap;
tmpEC = FacesContext.getCurrentInstance().getExternalContext();
sMap = tmpEC.getSessionMap();
login loginBean = (login) sMap.get("login");

How to Inject ManagedBeans in JSF2.0

I have got Controller-ManagedBeans and Model-ManagedBeans (like MVC-Pattern).
Here my Controller:
#ManagedBean
#RequestScoped
public class ProjectController {
private ProjectData projectBean; //The Model-ManagedBean (see below)!
private IProjectService projectService; //My Service-Layer
public ProjectController(){
init();
}
private void init(){
projectBean = new ProjectData();
projectService = new ProjectService();
}
public String saveProject() {
projectService.addProject(projectBean.getProjectDTO());
return ("");
}
}
...and her you can see my model, which gets its values out of a facelet...
#ManagedBean(name="ProjectData")
#SessionScoped
public class ProjectData {
private ProjectDTO projectDTO;
public ProjectData(){
projectDTO = new ProjectDTO();
}
public ProjectDTO getProjectDTO() {
return projectDTO;
}
public void setProjectDTO(ProjectDTO projectDTO) {
this.projectDTO = projectDTO;
}
public String getTitle() {
return projectDTO.getTitle();
}
public void setTitle(String title) {
projectDTO.setTitle(title);
}
}
My problem is now that it doesn't work. I think I need to inject the dependency between those two classes. But how? Is there a JSF-pro that can help me.
I would like to use annotations.
Thanks
Update after BalusC's post
I changed my code a little bit, but it still doesn't work. Any further advice, please.
#ManagedBean(name="projectData")
#SessionScoped
public class ProjectData {
...
#ManagedProperty(value="#{projectData}")
private ProjectData projectData;
The error com.sun.faces.mgbean.ManagedBeanCreationException says that the controller bean can not be created because projectData (the model-bean) is not found..
This should work:
#ManagedProperty(value="#{ProjectData}")
private ProjectData projectBean
That said, the normal practice is to start instance names with a lowercase. You also don't do in real
ProjectData ProjectData = new ProjectData();
but rather
ProjectData projectData = new ProjectData();
If you omit the (name="ProjectData") from the #ManagedBean, then it will automatically default to projectData.
As per your update:
The error com.sun.faces.mgbean.ManagedBeanCreationException says that the controller bean can not be created because projectData (the model-bean) is not found.
It's actually more telling that property projectData cannot be found. The property is not writable. In other words, the setter is missing. In the future please don't rephrase error messages and just copypaste them.
Okay guys I have found the answer:
there are missing get and set methods in my controller:
/*
* Getter and Setter
*/
public ProjectData getProjectData() {
return projectData;
}
public void setProjectData(ProjectData projectData) {
this.projectData = projectData;
}
Reference

Resources