Marius Richardsen

Greenhorn
+ Follow
since Apr 13, 2018
Marius likes ...
jQuery PHP Java
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
1
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Marius Richardsen

Rob Spoor wrote:There is one way I can think of: use MOXy instead of Jackson. That uses the declared type to do its mapping, not the actual type. I wouldn't want to use that myself though.

I've worked with MOXy when we were still using WebLogic (where it's the default JSON mapper), and due to some MOXy custom code we had we kept it when migrating to Spring Boot. It's not great though - if you want to use Spring MVC you need to build a bridge, because MOXy is built for JAX-RS. Its performance compared to Jackson or GSON is also pretty poor.

I'd do the simple thing - create a DTO or wrapper class for returning only the bare information.



Thank you. Seems like I will have to use DTO or wrapper class then.
1 year ago

Rob Spoor wrote:Please show some patience. Not everybody has a lot of time on their free Sundays. Also, please don't use any foul language in the future.

About your problem, I think this is something that some libraries (including Jackson) automatically do - they don't look at the declared type, but the actual type. They will therefore include any public property (either field or method based) that's not ignored. And that's where you should seek your solution - in ignoring properties.

I think in this case the easiest is to ignore everything by default, and only expose what you want. That means:
* Annotate your class with @JsonAutoDetect and set all visibility settings to Visibility.NONE.
* Use @JsonProperty on the fields, getters and setters you do want exposed.



Apologies. Now, your solution does work, however, it is not ideal in my situation. Because I have another endpoint: GET /users, which uses the authentication token sent in the header to determine current user, and then displays them. In this case, the User is only viewing their own information, and it should then also show private data such as email, which would then be ignored with your solution. Is there no other way other than creating wrapper objects that take each other as the parameter, and then only copies over some fields?
1 year ago
Hey! I have a very simple interface, as seen below. The point of this interface is to construct the base properties of a user, excluding any private information such as passwords and email.


Then I have my User entity class. This class implements the IUser, and introduces further properties such as passwords and email. This data is only to be viewed by the user themselves, and not other users.


Then I have my controller for /users/{user_id}, which other users can access. This is supposed to view only information in "IUser", but instead, it shows all the properties in "User" as well, which is bad for security. Note that I have enabled Web Support, so Spring automatically takes the user id provided and finds the user in the database.



It also does not show followers or following? Thanks for any help!

1 year ago

Rob Spoor wrote:As far as I know, JPA doesn't support performing custom queries on entity methods. I understand that getFollowers().size() is not something you want to do, because that will indeed load all followers. I'd therefore go for an extra method on my repository that performs a count on the user entity table. Your input should then be either the full user object, or only its id. It does mean that your code will have to call a method on the repository instead of the user.



Yes! And this is indeed something which I have done:


And in my user-service, which has auto-wired the JPA repository:


However, the issue is with this, is that I have to wrap everything with that UserService#loadPublic(User user)-- and it gets even more complicated when I want to fetch a following-relationship (Follower.class), which you know, has the "User" object inside and not the "PublicUser".


Are there no design patterns or Spring designs that allows for me to easily achieve this? I thought of maybe creating an User interface, which has all of the "public" information, then just have the User entity implement that, in which case all I have to call is:




However, then again, how do I get the amount of followers from within the User entity class? It's not like I can inject my followerService there, as it's not supposed to be a singleton.

1 year ago
Hey! I have my user entity setup like this:



And my /users controller setup like this:


This works. However, I'd like another property in "User", called "followersAmount". However, calling "User#getFollowers().size()" doesn't cut it, as it can be quite a lot of followers (1 million+), and I don't want to load them all (eager). Is there a way in Spring boot that can achieve that?
1 year ago

Tim Holloway wrote:Auto-wiring is used at construction time and it generally does not work well when trying to connect dynamic objects, such as data pulled from a database. At least I think that's what you are getting at.



I have followed the official Spring Boot tutorials when writing this. And it's not uncommon to set it up like I have, apparently.
1 year ago

Tim Holloway wrote:Your setup is very different than mine, and I'm not sure I really understand it.

I think you were asking if it was "wrong" to access an associated object when it was lazy-fetched and detached. It's not wrong, as such, but since the lazy object wasn't fetched before detachment, it will throw an exception. If you need to resolve an associated lazy object before detaching, there's no formal method, but simply referencing that object will fetch it and replace the dummy with the actual object. In other words, to force resolution of a Department record for an Employee, just do something throw-away like "thisEmployee.getDepartment().getId()". For collections (OneToMany, ManyToMany), iterate the collection. For best results, resolve both the forward and backward links, if they exist.


Let me describe how I do things. It's fairly simple and it has worked well for me.

I have basically 3 tiers for persistence in my JPA apps.

1. The bottom tier is the Entity classes themselves.

2. The next-level tier is DAOs. My DAOs are finders and CRUD methods for single-table operations. Or in some cases, where parent/child relationships are tightly bound, parent and child entity DAOs.

3. The top level is persistence services.

Most of my apps don't work on a single table at a time, they work on a network of related table objects. So the persistence services are responsible for making the necessary collection of data available to the non-persistence layer (business logic), and for persisting changes made to that collection of data ("working set"). Both the service tier and the DAO tier are transactional at the class level, although DAOs inherit the transaction context of the service method that calls them. To make things more predictable, DAOs are never called directly by business logic, only by persistence methods.

The service methods work with attached objects, so if I need to expand a working set (which is always detached), I'll pass that set to a service method that re-attaches, resolves whatever lazy dependencies I need resolved, and then returns a new detached instance of the working set with the new relationships in it. The service methods use the DAOs for the low-level work, so all DAOs have an EntityManager injected into them (I haven't been using the Spring CRUD repo). The service methods never use an EntityManager directly.



Thank you again for such a response. This is how I have my persistence setup:

1 - first I have my User model/entity, obviously. Which represents the model/entity in the database and defines the columns.



2 - the base layer is just a JpaRepository, same as CrudRepository but supports paging and some other stuff. Using this, I don’t have to write any manual SQL, Spring Data JPA will generate all that for me, which I want.



3 - then I have my service class, which wires in the repository



Now, whenever I want to find a User by their username, I just auto-wire that service class into the class I want to find the user in, and just call UserService.getUser(“their_username”).

This works perfectly. However, with lazily initialized collections in User, I can’t access them, even if I’m using @Transactional in the UserService class, and that’s my problem.

I wrote all of this on my phone, so I apologize for any spelling errors. Thank you again!
1 year ago

Tim Holloway wrote:If you use CrudRepository or JPARepository (or a subclass of one of them), then the EntityManager is used internally by their implementations. In my case, I use DAOs as repositories, so I inject an EntityManager via @PersistenceContext.

This might help: https://dzone.com/articles/accessing-the-entitymanager-from-spring-data-jpa



I saw multiple people online suggesting User#getFollowing().size(). However, for me, this just throws the same error? I also saw people suggest Hibernate.initialize(User#getFollowing()), however, they also said this would mean that you make your application rely on Hibernate, when you can only take the jpa-specific approach using #size().

I looked into the link you sent, and I think it can quickly get cumbersome. Are there any drawbacks of just using "followerService.getFollowing(user)"? Is it correct practise, or am I then violating some "law"? I guess accessing followers through the followerService is also better for me in the long run, as you might follow A LOT of people, in which case I might want to resort to paging through JpaRepository.
1 year ago
Thank you! I will look into that. Any reason you use DAO over JpaRepository?
1 year ago

Tim Holloway wrote:I'm rusty on JPA - people owe me money, so I found other things to do until they start paying me again.

However, I believe that merge() is an EntityManager method.

You'll know when you attempt to reference a detached lazy object. In fact, I think it throws an Exception if you even try.



I haven’t touched any EntityManager in my code. I use spring boot, and have managed so far only using JPA sql methods in interfaces that I make extend JpaRepository. Then I create a service class for each repository, and just auto-wire the repo and call the methods in the repo whenever I want to access my database. This seems like the cleanest way to do it, but I have no idea how to access lazy loaded items in my @Entity class.
1 year ago

Tim Holloway wrote:I think that "user" is a detached object. Lazy references cannot be resolved when an object is detached - in fact a dummy object is inserted in place of the lazy object or collection to alert you to that fact.

If that's what happened, you'll need to re-attach "user' by doing a JPA merge() before you can access its lazy collection of Post's. Note that merge does not return the same object back that you pass to it. Once merged, discard the original User object and use the merged User object instead.



Thank you so much for your reply! How do i find out whether it is a dummy object? Calling for example User#getId() returns the id that is also in the database. As you can see, I had commented out “followerService.getFollowing(user)”, which calls “findAllByFrom(User user)” in FollowersRepository extending JpaRepository. And it actually works, but I find it unneccecary to auto-wire the follower service when I can just call User#getFollowing(), but that doesn’t work.

Also, on what and where do I call the #merge()? Could you maybe provide a simple example if it’s not too much to ask for?
1 year ago