Mongo Java Connectivity - Only Insert once - spring-mvc

I have a Mongo - Java MVC Spring 4 connectivity. My insert operations work only once, they don't do a second insert in the collection. What could be the problem?
Here's my code.
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection="subject")
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
private int id;
private String name;
private String email;
private String address;
private String telephone;
strong text
...
public class EmployeeDAOImpl implements EmployeeDAO {
MongoTemplate mongoTemplate;
public MongoTemplate getMongoTemplate() {
return mongoTemplate;
}
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
#Override
public void addEmployee(Employee employee) {
mongoTemplate.save(employee);;
}
#Override
public List<Employee> getAllEmployees() {
// TODO Auto-generated method stub
return mongoTemplate.findAll(Employee.class);
}

#GeneratedValue(strategy=GenerationType.SEQUENCE) annotation is for JPA and not for Mongo.
Make sure that you import the #Id from the mongo package and ID should be auto generated by Mongo.
The first insert works because int has default value of 0 and the second time it tries to insert with the same key.
if you want to have custom ids generated, here is a great tutorial for that: https://www.baeldung.com/spring-boot-mongodb-auto-generated-field

Related

.Net Maui Binding ViewModel to SQLite database to populate CollectionView

I'm following Gerald Versluis's videos https://www.youtube.com/watch?v=uxqQqyuZ3Qo https://www.youtube.com/watch?v=8_cqUvriwM8
All good (and great teaching), but uses code behind and I'm trying to be a good boy and learn mvvm and binding - and wishing I perhaps hadn't ;)
So I can get the data from my database and convert to a List and then cycle through the list to add to an observable collection which is referenced in the Xaml's CollectionView ItemsSource=.
This seems pretty longwinded and not "reactive" (is that the right word?)
So my question is how do I link the CollectionView in the Xaml directly to the SQLite database (through the Database.cs)?
I'm using CommunityToolkit.Mvvm.ComponentModel; and I know how to use [ObservableProperty] and now how to setup a class to be reactive - see .net maui Cannot get updated fields in an Observable collection to update in bound collection view
Do I apply these to the Classes.Friend.cs class and does sqlite understand all that?
Ok here's some code snippets
MainPage.xaml
<CollectionView ItemsSource="{Binding FriendsOC}"
...
MainPage.xaml.cs --note the BindingContext here and not in xaml (refer .net Maui databinding to shell flyout item IsVisible property )
public MainPage()
{
InitializeComponent();
BindingContext = new CensusViewModel();
}
ViewModels.CensusViewModel.cs
public partial class CensusViewModel : ObservableObject
{
[ObservableProperty]
public ObservableCollection<Friend> friendsOC = new();
public CensusViewModel()
{
Console.WriteLine("heyupski G");
LoadData();
}
public async void LoadData() {
List<Friend> l = await App.Database.GetFriendsAsync();
foreach (Friend f in l)
{
FriendsOC.Add(f);
}
}
....
Database.Database.cs
public class Database
{
private readonly SQLiteAsyncConnection _database;
public Database(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<Friend>();
_database.CreateTableAsync<FSGroup>();
}
public Task<List<Friend>> GetFriendsAsync()
{
return _database.Table<Friend>().ToListAsync();
}
public Task<int> SaveFriendAsync(Friend friend)
{
return _database.InsertAsync(friend);
}
public Task<int> DeleteFriendAsync(Friend friend)
{
return _database.DeleteAsync(friend);
}
public Task<int> UpdateFriendAsync(Friend friend)
{
return _database.UpdateAsync(friend);
}
public Task<int> DeleteAllFriendsAsync() => _database.DeleteAllAsync<Friend>();
...
}
Classes.Friend.cs
public class Friend
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string LName { get; set; }
public string FName { get; set; }
I think that's it.
Yet again I also ask the question: is there a definitive tutorial/explanation on binding and mvvm, because this is like climbing a slippery pole and I'm just hacking...

AggregateMember inheritance: No handler was subscribed to command

I have the below aggregate which contains an aggregate member.
#Aggregate
public class CpaAggregate {
#AggregateIdentifier
private String externalId;
#AggregateMember
private Entity entity;
public CpaAggregate() {
}
#CommandHandler
public CpaAggregate(CreateCpaCommand cmd) {
AggregateLifecycle.apply(new CpaCreatedEvent(...));
}
#EventSourcingHandler
protected void on(CpaCreatedEvent evt) {
....
}
}
public class Entity {
#EntityId
private String entityId;
private Set<Identifier> identifiers = new HashSet<>();
public Entity() {
}
#EventSourcingHandler
public void on(IdentifiantUpdatedEvent evt) {
...
}
}
public class Laboratory extends Entity {
private OperatingSystem operatingSystem;
public Laboratory() {
}
#CommandHandler
public void handle(UpdateIdentifierLABCommand cmd) {
AggregateLifecycle.apply(new IdentifiantUpdatedEvent(....));
}
}
.
commandGateway.sendAndWait(new UpdateIdentifierLABCommand(...));
When i send a command to update an identifier of entity of type laboratory, i get this error
org.axonframework.commandhandling.NoHandlerForCommandException: No
handler was subscribed to command [UpdateIdentifierLABCommand]
I would model your CpaAggregate slightly differently, Aymen.
Instead of using the generic Entity aggregate member, I'd go for more specific entities like the Laboratory instance.
This is, for one, a lot more clear modeling-wise, as the model structure becomes clearer. Secondly, Axon Framework will move up into parent class for specifics. So, you can still have common information in an Entity class, like entity identifiers, command handlers, and event sourcing handlers.
I would thus adjust it like so:
#Aggregate
public class CpaAggregate {
#AggregateIdentifier
private String externalId;
#AggregateMember
private Laboratory laboratory;
public CpaAggregate() {
}
#CommandHandler
public CpaAggregate(CreateCpaCommand cmd) {
AggregateLifecycle.apply(new CpaCreatedEvent(...));
}
#EventSourcingHandler
protected void on(CpaCreatedEvent evt) {
....
}
}
This should ensure Axon Framework spots the command handler inside the aggregate member too, by the way.

Passing Arguments to classes extending the service class Java

I was wondering if there was a way to pass arguments the a class extending the Service class from the Javafx concurrent package. I would like ProteinariumThread to take in a String argument like ClusterID seen below:
public class ProteinariumThread extends Service<String>{
String ClusterID = "q";
#Override
protected Task<String> createTask(){
return new Task<String>() {
#Override
protected String call() throws Exception {
updateMessage("Running Proteinarium");
System.out.println("Asleep");
ProteinariumRun.PRun(ClusterID);
System.out.println("Woke Up");
String woke = "Woke Up";
return woke;
}
};
}
}
Currently in order to run this background task I use the following bit of code:
final ProteinariumThread service = new ProteinariumThread();
service.start();
This however does not allow me to take in a String argument. Is there anyway to make it that service.start() is able to take in String arguments so that String variable ClusterID can come from outside of the ProteinariumThread class?
final ProteinariumThread service = new ProteinariumThread();
service.start(ClusterID);
You just need to give your service class a constructor and/or method which accepts the necessary argument. As services are meant to be reusable, it'd probably be best to allow configuration throughout the service's lifetime by exposing a property:
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class ProteinariumService extends Service<String> {
private final StringProperty clusterId = new SimpleStringProperty(this, "clusterId");
public final void setClusterId(String clusterId) { this.clusterId.set(clusterId); }
public final String getClusterId() { return clusterId.get(); }
public final StringProperty clusterIdProperty() { return clusterId; }
public ProteinariumService() {}
public ProteinariumService(String clusterId) {
setClusterId(clusterId);
}
#Override
protected Task<String> createTask() {
return new Task<>() {
final String clusterId = getClusterId(); // cache configuration
#Override
protected String call() throws Exception {
...
}
};
}
}
It's important you copy the needed state from the service to the task since the task is executed on a background thread.
Then when you need to change the cluster ID you just do:
// or bind the property to something in the UI (e.g. a TextField)
theService.setClusterId(newClusterId);
theService.start();
If you really want to be able to do that in one line you can always define an overload for start in your service class:
public void start(String clusterId) {
setClusterId(clusterId):
start();
}

How do I setup/configure Jackson annotations to work in Spring MVC?

I inherited a project in Spring MVC 3.1.1 and I need to use Jackson to serialize objects to JSON. I have an object class like:
public class User {
Integer id;
String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and a controller like this:
#Controller
#RequestMapping(value = "/home")
public class homeController {
#RequestMapping(value = "/")
public #ResponseBody User home() {
User user;
user = new User();
user.setId(1);
user.setName("Drew");
return user;
}
}
Navigate to /home and I get:
{"id":1,"name":"Drew"}
Great, that's the first step down. Now, if I want to ignore the "id" parameter, the Jackson documentation says I should use the #JsonIgnore annotation. The problem I am having is that NetBeans can't locate any of the annotation packages to import for Jackson, so I can't use the annotations. I tried downloading the Jackson 2.2 jars and adding those to my project (which then allows me to import the annotations), but the #JsonIgnore annotation has no effect when I do that.
I suspect that I'm missing either a jar file from Spring MVC or I need to configure something in the project's XML files, how would I go about finding out whether either (or neither) is the case? I'm relatively new to Java and I've never used Spring before, so if there's some additional information that would be helpful that I didn't know you would need, please ask and I will do my best to locate it. Thanks in advance for any assistance you can give!
edit:
To clarify, I have tried using annotations like this:
public class User {
Integer id;
String name;
#JsonIgnore
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#JsonProperty("userName")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and like this:
#JsonIgnoreProperties({"id"})
public class User {
Integer id;
String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#JsonProperty("userName")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and the returned JSON is always the same:
{"id":1,"name":"Drew"}
You are missing Jackson dependencies on your classpath. You need to add dependencies on the following jars:
jackson-core
jackson-databind
jackson-annotations
Once you have those dependencies added you can prevent fields from being serialized by placing the #JsonIgnore annotation on the getter like so:
public class User {
Integer id;
String name;
#JsonIgnore
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Add Jackson JARs to your classpath. If you using Maven add Jackson2 as a dependency, or copy the required JARs to your classpath manually. Spring will do the rest.
Try using #JsonIgnoreProperties instead of #JsonIgnore
I ended up upgrading to Spring 3.2.2, which, along with the Jackson 2.2 libraries, fixed the problem. All of the Jackson annotations are working properly now. I assume that this means there was something wrong with the 3.1.1 installation that messed the Jackson stuff up, but who knows?
Thanks to everyone who responded.

Curiosities in deserializing collections with gson 2

I have these classes
public class Application {
public String name;
public String ico;
public List<MenuStruct> menu =new ArrayList<MenuStruct>();
//Constructor
public Application() { }
}
public class MenuStruct {
public String id;
public String type;
public String parent;
public String name;
public String secId;
//Constructor
public MenuStruct() {}
}
If I try to deserialize a collection directly in this way:
ApplicationManager apm= new ApplicationManager();
s="[ {\"name\":\"reg_salida\" , \"ico\":\"document-open-2-32x32.ico\" }]";
apm.apps=(new Gson()).fromJson(s,apm.apps.getClass() );
for (Application ap:apm.apps){
System.out.println(ap.name); //gets error here
}
I get a java.lang.ClassCastException.
But if I try to deserialize its containig class ApplicationManager it does not fail.
s="{ \"apps\": [ {\"name\":\"reg_salida\" , \"ico\":\"document-open-2-32x32.ico\" }]}";
ApplicationManager apm=(new Gson()).fromJson(s,ApplicationManager.class);
for (Application ap:apm.apps){
System.out.println(ap.name); // now no errors here! and shows reg_salida
}
Is this a bug of gson 2.2.4? or maybe I am doing something not correct?
Eduard.
You have to provide full definition of property class. Your example should looks like that:
manager.apps = gson.fromJson(json, new TypeToken<List<Application>>() {}.getType());

Resources