GWTP Gatekeeper - java

I do someexample from GWTP
http://blog.arcbees.com/2015/10/27/gwtp-beginners-tutorial-toaster-launcher-part-2/#Gatekeeper
#DefaultGatekeeper
public class LoggedInGatekeeper implements Gatekeeper {
private CurrentUser currentUser;
#Inject
public LoggedInGatekeeper(CurrentUser currentUser) {
this.currentUser = currentUser;
}
#Override
public boolean canReveal() {
return currentUser.isLoggedIn();
}
}
Here we give access if user is login.
Is it possible to find out which page (NameToken) wants to go by? And whether to give him a right, depending on the permissions

Sure, just inject a PlaceManager into your LoggedInGatekeeper and call getCurrentPlaceRequest and then compare it your NameToken. Something along these lines:
#DefaultGatekeeper
public class LoggedInGatekeeper implements Gatekeeper {
private CurrentUser currentUser;
private PlaceManager placeManager;
#Inject
public LoggedInGatekeeper(CurrentUser currentUser, PlaceManager placeManager) {
this.currentUser = currentUser;
this.placeManager = placeManager;
}
#Override
public boolean canReveal() {
PlaceRequest request = placeManager.getCurrentPlaceRequest();
if (request.hasSameNameToken('someNameToken') {
return currentUser.isLoggedIn();
}
return true;
}
}

Related

How to get values from an AsyncTask when it is in another class

I need to get the result from my AsyncTask. I can actually get the result from the task but I just don't know how to get it from the method that needs it. As will see, the AsyncTask is in a different class. If you have a question so I can clarify, please tell me so I can edit the post. See my code below:
public class UserRepository {
private UserDao userDao;
private User user;
private LiveData<List<User>> allUsers;
public UserRepository(Application application) {
AtsDatabase database = AtsDatabase.getInstance(application);
userDao = database.userDao();
allUsers = userDao.getUsers();
}
private MutableLiveData<User> userSearched = new MutableLiveData<>();
private void asyncFinished(User userResult) {
if(userResult == null) return;
Log.i("TAG", "asyncFinished: " + userResult.getLastName());
userSearched.setValue(userResult);
}
public LiveData<User> getUserByUserName(String userName) {
new GetUserByUserNameAsyncTask(userDao).execute(userName); ===> I NEED THE RESULT HERE SO I CAN PASS IT TO MY VIEW MODEL
}
public LiveData<List<User>> getAllUsers() { return allUsers; }
private static class InsertUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
private InsertUserAsyncTask(UserDao userDao) { this.userDao = userDao; }
#Override
protected Void doInBackground(User... users) {
userDao.insert(users[0]);
return null;
}
}
private static class GetUserByUserNameAsyncTask extends AsyncTask<String, Void, User> {
private LiveData<User> user;
private UserDao userDao;
private GetUserByUserNameAsyncTask(UserDao userDao) { this.userDao = userDao; }
#Override
protected User doInBackground(String... strings) {
user = userDao.getUserByUserName(strings[0]); ======> I GET RESULT HERE
return null;
}
#Override
protected void onPostExecute(User user) {
super.onPostExecute(user);
Log.i("TAG", "onPostExecute: "+user.getLastName());
delegate.asyncFinished(user);
}
}
}
How do I make this right? Thank you.
First of all, AsyncTask is now deprecated.
If you still want to use it, create a MutableLiveData and
return it as a LiveData in the exposed function, then pass it through the constructor of the AsyncTask.
Use the postValue method of the MutableLiveData to set the result after you get it.

Dagger 2 field injection is not working in Android

The issue is that I try to use field injection with Dagger 2, but at runtime field, that should be injected, always is null. Also I try to use MVVM pattern. Here is my code:
ProfileActivity.java:
#Override
protected void onStart() {
super.onStart();
Log.d(TAG, "ProfileActivity: onStart: ");
final ProfileViewModel profileViewModel
= ViewModelProviders.of(this).get(ProfileViewModel.class);
profileViewModel.init();
profileViewModel.getUser().observe(this, new Observer<User>() {
#Override
public void onChanged(#Nullable User user) {
if (user != null) {
Log.d(TAG, "ProfileActivity: onStart: " + user.toString());
} else {
Log.d(TAG, "ProfileActivity: onStart: user == null");
}
}
});
}
ProfileViewModel.java:
public class ProfileViewModel extends ViewModel {
private LiveData<User> user;
#Inject
UserRepository userRepository;
public ProfileViewModel() {
Log.d(TAG, "ProfileViewModel: Constructor: ");
}
public void init() {
Log.d(TAG, "ProfileViewModel: init: ");
user = userRepository.getUser();
}
public LiveData<User> getUser() {
Log.d(TAG, "ProfileViewModel: getUser: ");
return user;
}
}
UserRepository.java:
#Singleton
public class UserRepository {
private LiveData<User> user;
#Inject
public UserRepository() {
Log.d(TAG, "UserRepository: Constructor: ");
}
public LiveData<User> getUser() {
Log.d(TAG, "UserRepository: getUser: ");
if (user != null) {
return user;
} else {
// There should be userDao.load() call,
// but it had been omitted for brevity.
MutableLiveData<User> user = new MutableLiveData<>();
user.setValue(DB.getUser());
return user;
}
}
}
MyApplication.java:
public class MyApplication extends MultiDexApplication implements HasActivityInjector {
#Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
#Override
public void onCreate() {
super.onCreate();
DaggerMyApplicationComponent.create().inject(this);
}
#Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
}
MyApplicationModule.java:
#Module
public abstract class MyApplicationModule {
#ContributesAndroidInjector
abstract ProfileActivity contributeActivityInjector();
}
MyApplicationComponent.java:
#Component(modules = { AndroidInjectionModule.class, MyApplicationModule.class})
#Singleton
public interface MyApplicationComponent extends AndroidInjector<MyApplication> {
void inject(ProfileActivity profileActivity);
}
At runtime I can see the next logs:
ProfileActivity: onStart:
ProfileViewModel: Constructor:
ProfileViewModel: init:
And the app crashes on user = userRepository.getUser(); inside ProfileViewModel's init() method.
It means that UserRepository had not been injected. Also it is indicated by missing UserRepository: Constructor: log.
Where is my mistake? Thank you.
Basically what you need to do is to use ViewModel Factory to pass injected UserRepository into your ViewModels constructor, initialize it and then you will be able to use it. You cannot use field or parameter injections in ViewModels.
I would suggest you to follow this article: Add the new ViewModel to your MVVM
It provides enough sufficient information to begin using Dagger 2 with Architecture Components.
Hope it helps.

command pattern, why does this not work

I am implementing a command pattern in android.
This is what I have right now. For some reason this does not run. It is like the AddUserRequest is getting garbage collected for some reason.
RequestManager.java:
public class RequestManager extends BroadcastReceiver {
private static final RequestManager instance = new RequestManager();
private boolean isConnected = false;
private static ArrayList<Request> requestQueue = new ArrayList<Request>();
private RequestManager() {
}
/* singleton class */
public static RequestManager getInstance() {
return instance;
}
public void invokeRequest(Request request) {
request.execute(); // only to test this, this will change
return;
}
}
AddUserRequest.java
public class AddUserRequest extends InsertionRequest {
User user;
public AddUserRequest(User user) {
this.user = user;
}
public void execute() {
System.out.println("TEST!!!");
}
}
Request.java:
public abstract class Request {
public abstract void execute();
}
}
InsertionRequest.java
public abstract class InsertionRequest extends Request {
}
RequestManagerTest.java
public class RequestManagerTest extends ActivityInstrumentationTestCase2 {
public RequestManagerTest(){
super(MainActivity.class);
}
public void testAddUserRequest() {
User user = new User();
user.setName("Tester12345");
AddUserRequest request = new AddUserRequest(user);
RequestManager.getInstance().invokeRequest(request);
}
}
For some reason this does not print "TEST!!!" and for the life of me I cannot figure out why. I looked in the debug log and everytime request.execute() in RequestManager.java gets called there is a "GC Explicit..." which I suspect has to do with garbage collection. What is the proper way to do what I am trying to do?

How to inject into an interceptor?

I have configured a security-interceptor which should have the user-session object (which is a singleton) injected here is what I tried:
public DependencyInjection extends AbstractModule{
//Class that has AccessLevel Annoation
bind(InterfaceA.class).to(ImplA.class);
bind(UserPersistor.class).to(UserPersistorImpl.class);
//My session that I wish to inject
bind(UserSession.class).to(UserSessionHandler.class);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(AccessLevel.class),
new SecurityInterceptor(getProvider(UserSession.class)));
}
Here my UserSessionHandler:
#Singleton
public class UserSessionHandler implements UserSession {
private UserLevel userLevel = UserLevel.DEFAULT;
private final UserPersistor userPersistor;
#Inject
public UserSessionHandler(UserPersistor userPersistor) {
this.userPersistor = userPersistor;
}
#Override
public boolean loginUser(String userName, String password) {
Benutzer user = userPersistor.getUserByName(userName);
if (user == null) {
return false;
} else {
if (user.getKennwort().equals(password)) {
userLevel = UserLevel.valueOf(user.getRolleId().getBezeichnung().toUpperCase());
return true;
} else {
return false;
}
}
}
#Override
public boolean logoutUser() {
userLevel = UserLevel.DEFAULT;
return true;
}
#Override
public UserLevel getUserLevel() {
return userLevel;
}
}
Here how the SecurityInterceptor currently looks like:
#Singleton
public class SecurityInterceptor implements MethodInterceptor {
private final Provider<UserSession> session;
#Inject
public SecurityInterceptor(Provider<UserSession> session){
this.session = session;
}
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
AccessLevel[] acessRoles = invocation.getMethod().getAnnotationsByType(AccessLevel.class);
List<UserLevel> allowedRoles = new ArrayList<>();
for(AccessLevel accessRole: acessRoles){
allowedRoles.add(accessRole.value());
}
//Make sure that User has one of the allowed Access-Levels
if (!allowedRoles.contains(session.get().getUserLevel())) {
throw new InvalidAccessException("No Access allowed with userlevel" + session.get().getUserLevel());
}
return invocation.proceed();
}
}
Now I managed to get it working in my Mockito-Test with a binding to an instance like this:
bind(MockInterface.class).to(MockClass.class);
bind(UserSession.class).toInstance(user);
bind(UserPersistor.class).toInstance(mockUserPersistor);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(AccessLevel.class),
new SecurityInterceptor(getProvider(UserSession.class)));
However I don't want to create an instance myself but want the once guice is creating. How can I do that, or what am I currently doing wrong?
EDIT: My main issue is that the usersession seems to be different to the one that is generated. Here a simple example:
Injector injector = Guice.createInjector(new DependencyInjection());
UserSession session = injector.createInstance(UserSession.class);
InterfaceA methodCaller = injector.createInstance(InterfaceA.class);
if(session.loginUser("a","b")){
System.out.println(session.getUserLevel().toString()); //Returns Admin
}
methodCaller.callMethodWithAnnotation();
Now when I check the session.getUserLevel in the interceptor I get "Default"
EDIT2: My endgoal is to have the same session instance in my interceptor and anywhere I used UserSession

Hibernate is saving a completely new entity automatically(full stack of calls)

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.

Categories

Resources