I have created a web service and deplyed it on GlassFish on localhost.
#WebService
public class ProductCatalog {
ProductServiceImpl productService = new ProductServiceImpl();
public boolean addProductCategories(String category) {
return productService.addCategory(category);
}
public List<String> getProductCategories() {
return productService.getCategories();
}
}
My service class
public class ProductServiceImpl {
List<String> categories = new ArrayList<>();
public boolean addCategory(String categoryName) {
return categories.add(categoryName);
}
public List<String> getCategories() {
return categories;
}
}
Through the GF admin panel I checked both methods. They work. I can add a category or get all existing categories.
After that I imported the wsdl and got following classes.
Then I created a new project and added imported classes to it.
public class DataController {
public static void main(String[] args) {
String category = "Horror";
ProductCatalog productCatalog = new ProductCatalog() {
public boolean addProductCategories(String arg0) {
return false;
}
public List<String> getProductCategories() {
return null;
}
};
productCatalog.addProductCategories(category);
ProductCatalogService productCatalogService = new ProductCatalogService();
}
}
Now I wan't to add a new category, but have no idea how to do it.
This
productCatalog.addProductCategories(category);
doesn't work. The app runs, but when checking existing categories through GF admin panel, I see that none were added.
What is the reason?
I was using the wrong way. This is how it should be.
public class DataController {
public static void main(String[] args) {
String category = "Anime";
ProductCatalogService productCatalogService = new ProductCatalogService();
ProductCatalog productCatalog = productCatalogService.getProductCatalogPort();
productCatalog.addProductCategories(category);
List<String> categories = productCatalog.getProductCategories();
for(String categoryName : categories){
System.out.println(categoryName);
}
}
}
Related
I am at my last year at the university and working on my final project with a group of friends.
I am responsible on implementing the database (using google firestore in java) and i am trying to implement it using a design pattern.
I found the adapter quiet useful, as I can create an interface called:
GenericDB, which contains all the methods the database needs to use.
A concrete class, let's call her FirestoreDB which implements it,
and an Adapter, which also implements the GenericDB, and holds an Instance Of GenericDB as a variable, so I can choose at run time which db I will want to use (maybe in the future the db would change)
Here is some basic code:
public interface GenericDB {
boolean add(String... args);
boolean delete(String... args);
boolean get(String... args);
boolean changePassword(String... args);
}
public class FirestoreDB implements GenericDB {
private final Firestore db;
public FirestoreDB() {
FirestoreOptions firestoreOptions =
FirestoreOptions.getDefaultInstance().toBuilder()
.setProjectId(Constants.PROJECT_ID)
.build();
this.db = firestoreOptions.getService();
}
public boolean add(String... args) {
return true;
}
public boolean delete(String... args) {
return false;
}
public boolean get(String... args) {
return false;
}
public boolean changePassword(String... args) {
return false;
}
}
public class Adapter implements GenericDB {
private GenericDB db;
public Adapter(GenericDB db){
this.db = db;
}
public boolean add(String... args) {
return this.db.add(args);
}
public boolean delete(String... args) {
return db.delete(args);
}
public boolean get(String... args) {
return db.get(args);
}
public boolean changePassword(String... args) {
return db.changePassword(args);
}
}
public class DatabaseCreator {
public GenericDB getDB(DATABASE database) {
switch (database) {
case FIRESTORE:
return new FirestoreDB();
default:
return null;
}
}
DatabaseCreator database = new DatabaseCreator();
GenericDB db = database.getDB(EXTRA.DATABASE.FIRESTORE);
Adapter ad = new Adapter(db);
System.out.println(ad.add("1"));
Is this a good use of the adapter pattern?
Is this a good use of the adapter pattern?
What you call Adapter, is not an Adapter. Purpose of Adapter is to convert interface of the class to another interface expected by the client. But your 'adapter' implements the same GenericDB interface as the adaptee it wraps - no conversion happens here.
The closest one to Adapter is your FirestoreDB class. It is intended to convert the interface of Firestore to the interface GenericDB required by your code. Of course there is still small chance that Google will change Firestore to implement your GenericDB interface. Until then you should use an adapter.
To make FirestoreDB a proper adapter, you should pass adaptee (Firestore object) to the constructor of adapter, and later call it in the GenericDB methods implementation:
public class FirestoreAdapter implements GenericDB {
private final Firestore db;
public FirestoreAdapter(Firestore db) { // pass adaptee to adapter
this.db = db;
}
public boolean add(...) {
// DocumentReference docRef = db.collection(colName).document(docId);
// etc
}
// etc
}
This adapter could be passed to the code which expects GenericDB interface and knows nothing about Firestore interface:
FirestoreOptions firestoreOptions =
FirestoreOptions.getDefaultInstance().toBuilder()
.setProjectId(Constants.PROJECT_ID)
.build();
Firestore firestore = firestoreOptions.getService(); // but your code requires GenericDB
GenericDB db = new FirestoreAdapter(firestore); // adapt Firestore interface
// use db here as if Firestore was implementing your GenericDB interface
You can write adapters for another type of database in the same way. But... usually, you don't use some abstract database interface, because databases are very different with different sets of features. Trying to find some intersection of features supported by all databases might be not a great idea (unless you writing CosmosDB). Usually, you will work with higher-level abstractions, like Repositories.
You should use Command Design Pattern it more flexible than Adapter in your case
Example:
import java.util.HashMap;
import java.util.Map;
// demo for firestore
class Firestore {
private Map<Object, Object> map = new HashMap<>();
public void add(Object id, Object object) {
map.put(id, object);
}
public Object get(Object id) {
return map.get(id);
}
}
interface FirestoreAware {
void setFirestore(Firestore firestore);
}
enum CommandType {
ADD,
DELETE,
GET,
CHANGE_PASSWORD,
GET_USER
}
interface Command {
CommandType getType();
}
class GetCommand implements Command {
private int id;
public GetCommand id(int id) {
this.id = id;
return this;
}
public int getId() {
return id;
}
#Override
public CommandType getType() {
return CommandType.GET;
}
}
class AddCommand implements Command {
private int id;
private String jsonData;
public AddCommand id(int id) {
this.id = id;
return this;
}
public AddCommand jsonData(String jsonData) {
this.jsonData = jsonData;
return this;
}
public int getId() {
return id;
}
public String getJsonData() {
return jsonData;
}
#Override
public CommandType getType() {
return CommandType.ADD;
}
}
interface CommandHandler<C> {
Object handle(C cmd);
}
abstract class CommandFirestoreHandler<C>
implements CommandHandler<C>, FirestoreAware {
protected Firestore firestore;
#Override
public void setFirestore(Firestore firestore) {
this.firestore = firestore;
}
}
class AddCommandHandler extends CommandFirestoreHandler<AddCommand> {
#Override
public Object handle(AddCommand cmd) {
firestore.add(cmd.getId(), cmd.getJsonData());
return Boolean.TRUE;
}
}
class GetCommandHandler extends CommandFirestoreHandler<GetCommand> {
#Override
public Object handle(GetCommand cmd) {
return firestore.get(cmd.getId());
}
}
interface GenericDB {
<T> T execute(Command cmd);
}
class FirestoreDB implements GenericDB {
private final Firestore firestore;
private final Map<CommandType, CommandHandler> handlers;
public FirestoreDB() {
this(new Firestore());
}
public FirestoreDB(Firestore firestore) {
this.firestore = firestore;
this.handlers = new HashMap<>();
// demo add default command handlers
this.addHandler(CommandType.ADD, new AddCommandHandler());
this.addHandler(CommandType.GET, new GetCommandHandler());
}
public void addHandler(CommandType commandType, CommandHandler handler) {
if(handler instanceof FirestoreAware)
((FirestoreAware)handler).setFirestore(firestore);
this.handlers.put(commandType, handler);
}
#Override
public <T> T execute(Command cmd) {
CommandHandler handler = handlers.get(cmd.getType());
return (T)handler.handle(cmd);
}
}
class DatabaseCreator {
public GenericDB getDB(String database) {
switch (database) {
case "FIRESTORE":
return new FirestoreDB();
default:
return null;
}
}
}
public class GenericDBDemo {
public static void main(String[] args) {
DatabaseCreator database = new DatabaseCreator();
GenericDB db = database.getDB("FIRESTORE");
db.execute(new AddCommand().id(1).jsonData("{'_id': 1, 'name' : 'hello world'}"));
System.out.println(db.execute(new GetCommand().id(1)).toString());
}
}
I am very new in java reflection and generic types. I am now developing database handler library for android. I am stuck at returning array list from reflection.
for example:
This class is the library user's class
public class Creation extends SimpleDBHandler<Creation> {
private String tools;
private String nature;
public Creation(String tools,String nature) {
this.tools = tools;
this.nature = nature;
}
public String getTools() {
return tools;
}
public void setTools(String tools) {
this.tools = tools;
}
public String getNature() {
return nature;
}
public void setNature(String nature) {
this.nature = nature;
}
}
This class is the library user class
usage:
public class Main {
public static void main(String[] args) {
ArrayList<Creation> arrList = new ArrayList<>();
arrList = new SimpleDBHandler<Creation>().getAllData(Creation.class);
}
}
This is library class
public class SimpleDBHandler<T> {
public <T extends SimpleDBHandler<?>> ArrayList<T> getAllData(Class<?> mClass) {
ArrayList<T> arrList = new ArrayList<>();
// I am suck here. How to add data to arrList?
return arrList;
}
}
Please help me. Thanks before.
I am Using Play 2.3 (Java).
I have a onRequest method inside my Global.java file.
Following some answers on Stackoverflow and other resources, my Global.java is like -
private static ArrayList<String> admin_users = new ArrayList<String>();
public static ArrayList<String> getAdmin_users() {
return admin_users;
}
public static void setAdmin_users(ArrayList<String> admin_users) {
Global.admin_users = admin_users;
}
#Override
public void onStart(play.Application arg0) {
ArrayList<String> admins = new ArrayList<String>();
admins.add("aahuja");
admins.add("chlr");
admins.add("bobba");
setAdmin_users(admins);
}
private static ArrayList<String> admin_users = new ArrayList<String>();
public static ArrayList<String> getAdmin_users() {
return admin_users;
}
public static void setAdmin_users(ArrayList<String> admin_users) {
Global.admin_users = admin_users;
}
#Override
public void onStart(play.Application arg0) {
ArrayList<String> admins = new ArrayList<String>();
admins.add("aahuja");
admins.add("chlr");
admins.add("bobba");
setAdmin_users(admins);
}
private class ActionWrapper extends Action.Simple {
private String user;
public ActionWrapper(Action<?> action, String user) {
this.delegate = action;
this.user = user;
}
#Override
public Promise<Result> call(Http.Context ctx) throws java.lang.Throwable {
Promise<Result> result = this.delegate.call(ctx);
ctx.args.put("Name", this.user);
}
#Override
public Action<?> onRequest(Http.Request request, java.lang.reflect.Method actionMethod) {
if(request.getHeader("OriginalName") != null){
if(getAdmin_users().contains(request.getHeader("OriginalName"))){
if(request.hasHeader("IMPERSONATE") && request.getHeader("IMPERSONATE").equals("true")){
return new ActionWrapper(super.onRequest(request, actionMethod), request.getHeader("IMPERSONATE-IDENTITY"));
}
}
return new ActionWrapper(super.onRequest(request, actionMethod), request.getHeader("OriginalName"));
}
else
return super.onRequest(request, actionMethod);
}
Now, inside my controller file, I have a method like this -
public static Promise<Result> all() {
String name = (String) ctx().args.get("Name");
System.out.println(name);
// rest of code
}
Now when I pass a request to this application with the header information like -
OriginalName: abcd, I get a value of null inside my controller printed out.
Is ctx the correct way to pass data? If not whats the correct way.
I am trying to take the redundant logic out of the main business logic.
The same can also be achieved if we are able to modify the header information when it gets passed from the interceptor to the controller. But I cant find any suitable way of doing so.
Try to put the ctx.args.put() before calling the delegate:
#Override
public Promise<Result> call(Http.Context ctx) throws java.lang.Throwable {
ctx.args.put("Name", this.user);
Promise<Result> result = this.delegate.call(ctx);
}
You are setting the value afther your action run. So you cannot access the value inside your action.
Consider the following JMX code:
public class UserJMXBeanExpose {
private UserJMXBeanImpl userJMXBean;
#Required
public void setUserJMXBean(UserJMXBeanImpl userJMXBean) {
this.userJMXBean = userJMXBean;
}
public void init() throws MBeanRegistrationException, InstanceAlreadyExistsException, NotCompliantMBeanException, MalformedObjectNameException {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName objectName = new ObjectName("MineStar:type=UserJMXBeanExpose,name=Statistics");
MineStarMBean impl = new MineStarMBean();
impl.addProperty(new PropertyAdapter("User", "User List", "java.lang.String") {
public Object getValue() {
if (userJMXBean == null) return 0;
return userJMXBean.getUserAttributes();
}
});
server.registerMBean(impl, objectName);
}
}
And this code:
public class UserJMXBeanImpl implements UserJMXBean {
private List<User> userList = new ArrayList<>();
public void addUser(User user){
userList.add(user);
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
public String[] getUserAttributes(){
for(User user : this.getUserList()){
return new String[]{user.getUserId(),user.getRoles()};
}
return null;
}
}
How can I add a listener to JMX so that it updates the values of getUserAttributes() with the newly added user by UserJMXBeanImpl class?
I need to update my jmx information when each new user is added to the impl class. Or how can we add listener so that it can notify the UserJMXBeanExpose to expose its data whenever a new user is added to impl class?
I have already asked this question two times, but I'm new to stackoverflow and it seems that I don't know the rules for formatting my example code in here. Now I've decided to give the full stack of the calls and I hope I can explain the situation because everything is so strange and I can't find the words to describe it. First I will give you the source of the classes that have something to do with the problem. My actual question is in the end of the page. The large piece of code is just in case, because I don't know what could be the explanation of my problem.
Here is a service facade that gets calls from my flex application.
public class ServiceFacade implements IAuthenticationService, IProfileService, ICampaignService {
#Autowired
private IAuthenticationService authenticationService;
#Autowired
private IProfileService profileService;
#Autowired
private ICampaignService campaignService;
public void login(User user) throws AuthenticationException{
authenticationService.login(user);
}
#Override
public void logout() throws AuthenticationException {
authenticationService.logout();
}
#Override
public void sendForgottenPassword(String email) {
authenticationService.sendForgottenPassword(email);
}
#Override
public Profile getProfile(Long userId) {
return profileService.getProfile(userId);
}
#Override
public Profile updateProfile(Profile profile) {
return profileService.updateProfile(profile);
}
#Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileService.getSocialConnectionsTypes(userId);
}
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileService.findDuplicateEmails(profileId, emails);
}
#Override
public Campaign getCampaign(Long campaignId) {
return campaignService.getCampaign(campaignId);
}
#Override
public Campaign updateCampaign(Campaign campaign) {
return campaignService.updateCampaign(campaign);
}
#Override
public void removeCampaign(Long campaignId) {
campaignService.removeCampaign(campaignId);
}
#Override
public void setPools(Long campaignId, Collection<Pool> pools) {
campaignService.setPools(campaignId, pools);
}
#Override
public void addPool(Long campaignId, Pool pool) {
campaignService.addPool(campaignId, pool);
}
#Override
public void removePool(Long campaignId, Pool pool) {
campaignService.removePool(campaignId, pool);
}
#Override
public List<Campaign> getCampaigns() {
return campaignService.getCampaigns();
}
#Override
public void updatePool(Long campaignId, Pool pool) {
campaignService.updatePool(campaignId, pool);
}
}
The method which is important for my question is the findDuplicateEmails method.
The profileService is implemented in the following class:
public class ProfileService implements IProfileService {
#Autowired
private IProfileManager profileManager;
#Override
public Profile getProfile(Long userId) {
return profileManager.getProfile(userId);
}
#Override
public Profile updateProfile(Profile profile){
profileManager.updateProfile(profile);
return profile;
}
#Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileManager.getSocialConnectionsTypes(userId);
}
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileManager.findDuplicateEmails(profileId, emails);
}
}
Again the important method is findDuplicateEmails
The implementation of the profileManager is the following class:
public class ProfileManager implements IProfileManager {
#Autowired
private IProfileDao profileDao;
#Autowired
private ISectionManager autoCompleteManager;
#Autowired
private IUserSecurityService userSecurityService;
#Transactional
public Profile getProfile(Long userId) {
return profileDao.getProfileByUser(userId);
}
#Transactional
public void updateProfile(final Profile profile) {
List<Major> notApprovedMajors = extractNotApprovedMajors(profile);
List<Degree> notApprovedDegrees = extractNotApprovedDegrees(profile);
List<School> notApprovedSchools = extractNotApprovedSchools(profile);
List<Language> notApprovedLanguages = extractNotApprovedLanguages(profile);
List<Position> notApprovedPositions = extractNotApprovedPositions(profile);
List<Company> notApprovedCompanies = extractNotApprovedCompanies(profile);
List<Country> notApprovedCountries = extractNotApprovedCountries(profile);
List<City> notApprovedCities = extractNotApprovedCities(profile);
List<Certificate> notApprovedCertificates = extractNotApprovedCertificates(profile);
autoCompleteManager.updateAll(notApprovedMajors);
autoCompleteManager.updateAll(notApprovedDegrees);
autoCompleteManager.updateAll(notApprovedSchools);
autoCompleteManager.updateAll(notApprovedLanguages);
autoCompleteManager.updateAll(notApprovedPositions);
autoCompleteManager.updateAll(notApprovedCompanies);
autoCompleteManager.updateAll(notApprovedCountries);
autoCompleteManager.updateAll(notApprovedCities);
autoCompleteManager.updateAll(notApprovedCertificates);
profileDao.updateProfile(profile);
}
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Profile persistedProfile = profileDao.findById(profileId);
if (persistedProfile.getContact() == null)
{
persistedProfile.setContact(new Contact());
}
List<Email> resultEmails = new ArrayList<Email>();
for (int i = 0; i < emails.size(); i++) {
if ((!userSecurityService.guaranteeUniquePrincipal(emails.get(i)) &&
!isPersistedInThePersistentCollection(emails.get(i), persistedProfile.getContact().getEmails())) ||
isDuplicateInTheCurrentCollection(emails.get(i), emails, i + 1)) {
resultEmails.add(emails.get(i));
}
}
return resultEmails;
}
private boolean isDuplicateInTheCurrentCollection(Email emailToCheck, List<Email> emails, int index)
{
for (int i = index ; i < emails.size(); i ++) {
if (emails.get(i).getEmailAddress().equals(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
private boolean isPersistedInThePersistentCollection(Email emailToCheck, Collection<Email> emails)
{
if (emails == null) {
return false;
}
for (Email persistedEmail : emails) {
if (persistedEmail.getEmailAddress().equalsIgnoreCase(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
}
Again the important method is the method findDuplicateEmails
Now, after this short background, here is my problem:
I am using Hibernate with spring's HibernateTemplate. I found out that in the method findDuplicateEmails, some completely new entities which come form the flex application gets saved automatically. This was very strange and during the debbugging I found out that even if I change the method findDuplicateEmails in the ProfileManager so it looks like:
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Email email = new Email();
return null;
}
the entity email gets saved automatically. I also found out that if the identifier of the entity is not "email", but something else, like "newEmail", or "email1", or something, there is no problem and the entity gets persisted if and only if I make it persistent. This problem exists only in this class and finally, this problem shows up only for the Email. I mean that if I have Phone phone = new Phone(); the entity phone gets persisted only when I wish.
The flex application first checks that the entered from the user emails are unique, and then after some user interaction calls the method updateProfile() if the entered data is valid.
I would download Hibernate sources and start debugging, you will either find a bug in Hibernate (happens) or in your code, as this is one weird behavior.
This is an advice I got once, and was the fastest, most educating way to get to the root.