I'm using the Gson library and jakarta. Although I have been able to use the conversion in CarrinhoResource.java as below, my ClienteTest.java cannot use the String content (already in json) inside the cart. I cant run my test a just only message into my intellij is (Cannot resolve method 'fromJson(java.lang.String)').
Can someone help me?
Class CarrinhoResource.java
package br.com.alura.loja.resource;
import br.com.alura.loja.dao.CarrinhoDAO;
import br.com.alura.loja.modelo.Carrinho;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
#Path("/v1/carrinhos")
public class CarrinhoResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public String busca(){
Carrinho carrinho = new CarrinhoDAO().busca(1L);
return carrinho.toJson();
}
}
Carrinho.java
package br.com.alura.loja.modelo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.google.gson.Gson;
public class Carrinho {
private List<Produto> produtos = new ArrayList<Produto>();
private String rua;
private String cidade;
private long id;
public Carrinho adiciona(Produto produto) {
produtos.add(produto);
return this;
}
public Carrinho para(String rua, String cidade) {
this.rua = rua;
this.cidade = cidade;
return this;
}
public Carrinho setId(long id) {
this.id = id;
return this;
}
public String getRua() {
return rua;
}
public void setRua(String rua) {
this.rua = rua;
}
public void setCidade(String cidade) {
this.cidade = cidade;
}
public long getId() {
return id;
}
public void remove(long id) {
for (Iterator iterator = produtos.iterator(); iterator.hasNext();) {
Produto produto = (Produto) iterator.next();
if(produto.getId() == id) {
iterator.remove();
}
}
}
public void troca(Produto produto) {
remove(produto.getId());
adiciona(produto);
}
public void trocaQuantidade(Produto produto) {
for (Iterator iterator = produtos.iterator(); iterator.hasNext();) {
Produto p = (Produto) iterator.next();
if(p.getId() == produto.getId()) {
p.setQuantidade(produto.getQuantidade());
return;
}
}
}
public List<Produto> getProdutos() {
return produtos;
}
public String toJson() {
return new Gson().toJson(this);
}
}
ClienteTest.java
package br.com.alura.loja;
import br.com.alura.loja.modelo.Carrinho;
import com.google.gson.*;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import org.junit.Assert;
import org.junit.Test;
public class ClienteTest {
#Test
public void testaConexaoServidor() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8085");
String conteudo = target.path("/v1/carrinhos").request().get(String.class);
Carrinho carrinho = (Carrinho) new Gson().fromJson(conteudo); **//Cannot resolve method 'fromJson(java.lang.String)'/**
System.out.println(carrinho);
Assert.assertEquals("Rua Vergueiro, 3185", carrinho.getRua());
}
}
Carrinho carrinho = (Carrinho) new Gson().fromJson(conteudo); **//Cannot resolve method 'fromJson(java.lang.String)'/**
The reason for this is that there is no Gson.fromJson(String) method, see the Gson class documentation. For deserialization Gson needs to know which type you are expecting, so all fromJson methods have a second parameter representing the type.
You can simply change your code to:
Carrinho carrinho = new Gson().fromJson(conteudo, Carrinho.class);
Related
There is commandline app to show tomorrow's forecast using a public API
Sample output could be as follows:
Tomorrow (2019/05/01) in city XYZ:
Clear
Temp: 26.5 °C
Wind: 7.6 mph
Humidity: 61%
Question : How will you create a test case such that tests should not touch the real service and work without the Internet.
I tried creating the junit test for the same and its working fine till the time i am using the api directly.
Can someone please help how can i create a mock for my unit testing.
App.java
import api.ForecastServiceImpl;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.io.IOException;
import java.time.LocalDate;
public class App {
public static void main(String[] args) throws IOException {
if (args.length < 1) {
System.out.println("Pass city name as an argument");
System.exit(1);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.metaweather.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
LocalDate tomorrow = LocalDate.now().plusDays(1);
ForecastServiceImpl service = new ForecastServiceImpl(retrofit);
System.out.println(service.getForecast(args[0], tomorrow));
}
}
ForecastServiceImpl.java
package api;
import model.City;
import model.Forecast;
import retrofit2.Call;
import retrofit2.Retrofit;
import util.PathDate;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
public class ForecastServiceImpl {
private Retrofit retrofit;
public ForecastServiceImpl(Retrofit retrofit) {
this.retrofit = retrofit;
}
public String getForecast(String cityName, LocalDate date) throws IOException {
PathDate pathDate = new PathDate(date);
ForecastService service = retrofit.create(ForecastService.class);
Call<List<City>> findCityCall = service.findCityByName(cityName.toLowerCase());
City city = Objects.requireNonNull(findCityCall.execute().body())
.stream()
.findFirst()
.orElseThrow(() -> new RuntimeException(String.format("Can't find city id for %s", cityName)));
Call<List<Forecast>> forecastCall = service.getForecast(city.getWoeid(), pathDate);
Forecast forecast = Objects.requireNonNull(forecastCall.execute().body())
.stream()
.findFirst()
.orElseThrow(() -> new RuntimeException(String.format("Can't get forecast for %s", cityName)));
return String.format("Weather on (%s) in %s:\n%s", pathDate, city.getTitle(), forecast);
}
}
ForecastService.java
package api;
import model.City;
import model.Forecast;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
import util.PathDate;
import java.util.List;
public interface ForecastService {
#GET("/api/location/{city_id}/{date}/")
Call<List<Forecast>> getForecast(#Path("city_id") Long cityId, #Path("date") PathDate date);
#GET("/api/location/search/")
Call<List<City>> findCityByName(#Query("query") String city);
}
City.java
package model;
public class City {
private String title;
private Long woeid;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Long getWoeid() {
return woeid;
}
public void setWoeid(Long woeid) {
this.woeid = woeid;
}
}
Forecast.java
package model;
import com.google.gson.annotations.SerializedName;
public class Forecast {
private Long id;
#SerializedName("weather_state_name")
private String weatherState;
#SerializedName("wind_speed")
private Double windSpeed;
#SerializedName("the_temp")
private Double temperature;
private Integer humidity;
public Long getId() {
return id;
}
public Forecast setId(Long id) {
this.id = id;
return this;
}
public String getWeatherState() {
return weatherState;
}
public Forecast setWeatherState(String weatherState) {
this.weatherState = weatherState;
return this;
}
public Double getWindSpeed() {
return windSpeed;
}
public Forecast setWindSpeed(Double windSpeed) {
this.windSpeed = windSpeed;
return this;
}
public Double getTemperature() {
return temperature;
}
public Forecast setTemperature(Double temperature) {
this.temperature = temperature;
return this;
}
public Integer getHumidity() {
return humidity;
}
public Forecast setHumidity(Integer humidity) {
this.humidity = humidity;
return this;
}
#Override
public String toString() {
return String.format("%s\nTemp: %.1f °C\nWind: %.1f mph\nHumidity: %d%%",
weatherState, temperature, windSpeed, humidity);
}
}
PathDate.java
package util;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class PathDate {
private final LocalDate date;
public PathDate(LocalDate date) {
this.date = date;
}
#Override public String toString() {
return date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
}
}
Utils.java
package util;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Utils {
public static byte[] readResourceFileToBytes(String filename) {
byte[] fileBytes = new byte[0];
try {
Path path = Paths.get(Utils.class.getClassLoader().getResource(filename).toURI());
fileBytes = Files.readAllBytes(path);
} catch (URISyntaxException|IOException|NullPointerException e) {
e.printStackTrace();
}
return fileBytes;
}
}
The service.getForecast(city.getWoeid(), pathDate); returns us a Call<List<Forecast>> object. And when we call execute on this object then an actual API call is made. Since we don't want to do an actual API call, we can try mocking the Call<List<Forecast>> object.
We can mock the Call class like
Call<List<Forecast>> mockedListForeCast = mock(Call.class);
The above statement creates a mock object of Call<List<Forecast>>. We can use when to define what should happen when a method is called on the mocked object.
// here I am returning the singleton list, you can return a list of forecast
when(mockedListForeCast.execute()).thenReturn(Response.success(Collections.singletonList()));
The above line says that return an empty list of forecast when the execute function was called on the mocked object.
This way we are mocking the API response and we don't have to do an actual API call.
Edit:
You can also mock your retrofit API using Retrofit Mock also.
I am stuck with implementing a TypeConverter to my Database. I have added the TypeConverters but it still keeps saying that it cannot figure out how to save the field into the database. Or maybe I have missed something? I was following this article to create TypeConverters (https://android.jlelse.eu/room-persistence-library-typeconverters-and-database-migration-3a7d68837d6c), which is with my knowledge so far a bit hard to understand.
Any help would be appreciated!
MyGame.java:
package com.riceplant.capstoneproject.room;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import com.riceplant.capstoneproject.data.Cover;
import com.riceplant.capstoneproject.data.Genre;
import com.riceplant.capstoneproject.data.Platform;
import com.riceplant.capstoneproject.data.ReleaseDate;
import com.riceplant.capstoneproject.data.Video;
import java.util.List;
#Entity(tableName = "game")
public class MyGame {
#PrimaryKey(autoGenerate = true)
private Integer mId;
private Cover mCover;
private String mName;
private Double mPopularity;
private String mSummary;
private List<Genre> mGenres;
private List<Platform> mPlatform;
private Double mRating;
private List<ReleaseDate> mReleaseDate;
private List<Video> mVideos;
#Ignore
public MyGame() {
}
public MyGame(Integer id,
Cover cover,
String name,
Double popularity,
String summary,
List<Genre> genres,
List<Platform> platform,
Double rating,
List<ReleaseDate> releaseDate,
List<Video> videos) {
mId = id;
mCover = cover;
mName = name;
mPopularity = popularity;
mSummary = summary;
mGenres = genres;
mPlatform = platform;
mRating = rating;
mReleaseDate = releaseDate;
mVideos = videos;
}
public Integer getId() {
return mId;
}
public void setId(Integer id) {
id = mId;
}
public Cover getCover() {
return mCover;
}
public void setCover(Cover cover) {
cover = mCover;
}
public String getName() {
return mName;
}
public void setName(String name) {
name = mName;
}
public Double getPopularity() {
return mPopularity;
}
public void setPopularity(Double popularity) {
popularity = mPopularity;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String summary) {
summary = mSummary;
}
public List<Genre> getGenres() {
return mGenres;
}
public void setGenres(List<Genre> genres) {
genres = mGenres;
}
public List<Platform> getPlatform() {
return mPlatform;
}
public void setPlatform(List<Platform> platform) {
platform = mPlatform;
}
public Double getRating() {
return mRating;
}
public void setRating(Double rating) {
rating = mRating;
}
public List<ReleaseDate> getReleaseDate() {
return mReleaseDate;
}
public void setReleaseDate(List<ReleaseDate> releaseDate) {
releaseDate = mReleaseDate;
}
public List<Video> getVideos() {
return mVideos;
}
public void setVideos(List<Video> videos) {
videos = mVideos;
}
}
Converters.java
package com.riceplant.capstoneproject.room;
import androidx.room.TypeConverter;
import com.riceplant.capstoneproject.data.Cover;
import com.riceplant.capstoneproject.data.Genre;
import com.riceplant.capstoneproject.data.Platform;
import com.riceplant.capstoneproject.data.Video;
public class Converters {
#TypeConverter
public static Cover toCover(String value) {
return value == null ? null : new Cover();
}
#TypeConverter
public static String toString(Cover value) {
return value == null ? null : value.getUrl();
}
#TypeConverter
public static Genre toGenre(String value) {
return value == null ? null : new Genre();
}
#TypeConverter
public static String toString(Genre value) {
return value == null ? null : value.getName();
}
#TypeConverter
public static Platform toPlatform(String value) {
return value == null ? null : new Platform();
}
#TypeConverter
public static String toString(Platform value) {
return value == null ? null : value.getName();
}
#TypeConverter
public static Video toString(String value) {
return value == null ? null : new Video();
}
#TypeConverter
public static String toVideo(Video value) {
return value == null ? null : value.getVideoId();
}
}
GameRoomDatabase.java
package com.riceplant.capstoneproject.room;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;
#Database(entities = {MyGame.class}, version = 3, exportSchema = false)
#TypeConverters({Converters.class})
public abstract class GameRoomDatabase extends RoomDatabase {
private static final String LOG_TAG = GameRoomDatabase.class.getSimpleName();
private static final Object LOCK = new Object();
private static final String DATABASE_NAME = "gameslist";
private static GameRoomDatabase sInstance;
public static GameRoomDatabase getInstance(Context context) {
if (sInstance == null) {
synchronized (LOCK) {
sInstance = Room.databaseBuilder(context.getApplicationContext(),
GameRoomDatabase.class, GameRoomDatabase.DATABASE_NAME)
.fallbackToDestructiveMigration()
.build();
}
}
return sInstance;
}
public abstract GameDao gameDao();
}
GameDao.java
package com.riceplant.capstoneproject.room;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
#Dao
public interface GameDao {
#Query("SELECT * FROM game ORDER BY mId")
LiveData<List<MyGame>> loadAllGames();
#Insert
void insertGame(MyGame myGame);
#Update(onConflict = OnConflictStrategy.REPLACE)
void updateGame(MyGame myGame);
#Delete
void deleteGame(MyGame myGame);
#Query("SELECT * FROM game WHERE mId = :id")
MyGame loadGameById(int id);
}
GameViewModel
package com.riceplant.capstoneproject.room;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import java.util.List;
public class GameViewModel extends AndroidViewModel {
private LiveData<List<MyGame>> games;
public GameViewModel(#NonNull Application application) {
super(application);
GameRoomDatabase database = GameRoomDatabase.getInstance(this.getApplication());
games = database.gameDao().loadAllGames();
}
public LiveData<List<MyGame>> getGames() {
return games;
}
}
Your DB contains Lists of Genre, Platform, ReleaseDate and Video. SQLite supports column types of INTEGER, REAL, TEXT and BLOB. You must provide methods for conversion of your List types to/from String(TEXT) or one of the other supported SQLite types.
For example:
#TypeConverter
public static List<Genre> toGenreList(String value) {
// TODO conversion code
}
#TypeConverter
public static String toString(List<Genre> value) {
// TODO conversion code
}
Well, my issue is related to when I try to save an entity (Parade) which has a collection of other entity (AcmeFloat) using the corresponding default CRUD method in convenient repository (the code is attached below). When it reaches the save() method, it throws an exception.
I tried to save the pertinent entities of AcmeFloat class which need to be updated by hand, but, whatever I do (whether save first the Parade updated and later update and save each AcmeFloat or inside out) raises an exception.
So I went into Stack Overflow and the solution I found is putting a 'cascade=CascadeType.ALL' inside the #ManyToMany anotation, without success. I tried also to do both things, which also fails.
Here is the code:
Parade (Domain Class):
package domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.Valid;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;
#Entity
#Access(AccessType.PROPERTY)
public class Parade extends DomainEntity {
// Fields -----------------------------------------------------------------
private String title;
private String description;
private Date moment;
private String ticker;
private boolean isDraft;
// Relationships ----------------------------------------------------------
private Brotherhood brotherhood;
private Collection<AcmeFloat> acmeFloats;
// Field access methods ---------------------------------------------------
#NotBlank
public String getTitle() {
return this.title;
}
public void setTitle(final String title) {
this.title = title;
}
#NotBlank
public String getDescription() {
return this.description;
}
public void setDescription(final String description) {
this.description = description;
}
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")
public Date getMoment() {
return this.moment;
}
public void setMoment(final Date moment) {
this.moment = moment;
}
#NotBlank
#Pattern(regexp = "^([\\d]){6}-([A-Z]){5}$")
#Column(unique = true)
public String getTicker() {
return this.ticker;
}
public void setTicker(final String ticker) {
this.ticker = ticker;
}
#Basic
public boolean getIsDraft() {
return this.isDraft;
}
public void setIsDraft(final boolean isDraft) {
this.isDraft = isDraft;
}
// Relationship access methods --------------------------------------------
#Valid
#ManyToOne(optional = true)
public Brotherhood getBrotherhood() {
return this.brotherhood;
}
public void setBrotherhood(final Brotherhood brotherhood) {
this.brotherhood = brotherhood;
}
#Valid
#ManyToMany(mappedBy = "parades", cascade = CascadeType.ALL)
public Collection<AcmeFloat> getAcmeFloats() {
return new ArrayList<AcmeFloat>(this.acmeFloats);
}
public void setAcmeFloats(final Collection<AcmeFloat> acmeFloats) {
this.acmeFloats = acmeFloats;
}
}
AcmeFloat (Domain Class):
package domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.NotBlank;
#Entity
#Access(AccessType.PROPERTY)
public class AcmeFloat extends DomainEntity {
// Fields -----------------------------------------------------------------
private String title;
private String description;
private List<String> pictures;
// Relationships ----------------------------------------------------------
private Collection<Parade> parades;
private Brotherhood brotherhood;
// Field access methods ---------------------------------------------------
#NotNull
#NotBlank
public String getTitle() {
return this.title;
}
public void setTitle(final String title) {
this.title = title;
}
#NotNull
#NotBlank
public String getDescription() {
return this.description;
}
public void setDescription(final String description) {
this.description = description;
}
//Optional
//#URL
#NotNull
#ElementCollection
public List<String> getPictures() {
return this.pictures;
}
public void setPictures(final List<String> pictures) {
this.pictures = pictures;
}
// Relationship access methods --------------------------------------------
#ManyToMany(cascade = CascadeType.ALL)
#Valid
public Collection<Parade> getParades() {
return this.parades;
}
public void setParades(final Collection<Parade> parades) {
this.parades = new ArrayList<Parade>(parades);
}
#ManyToOne
#Valid
public Brotherhood getBrotherhood() {
return this.brotherhood;
}
public void setBrotherhood(final Brotherhood brotherhood) {
this.brotherhood = brotherhood;
}
}
ParadeForm (Form Object):
package forms;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.springframework.format.annotation.DateTimeFormat;
import domain.AcmeFloat;
public class ParadeForm {
// Fields -----------------------------------------------------------------
private int id;
private String title;
private String description;
private Date moment;
// Relationships ----------------------------------------------------------
private Collection<AcmeFloat> acmeFloats;
// Field access methods ---------------------------------------------------
#Range(min = 0)
public int getId() {
return this.id;
}
public void setId(final int id) {
this.id = id;
}
#NotBlank
public String getTitle() {
return this.title;
}
public void setTitle(final String title) {
this.title = title;
}
#NotBlank
public String getDescription() {
return this.description;
}
public void setDescription(final String description) {
this.description = description;
}
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")
public Date getMoment() {
return this.moment;
}
public void setMoment(final Date moment) {
this.moment = moment;
}
// Relationship access methods --------------------------------------------
#NotNull
public Collection<AcmeFloat> getAcmeFloats() {
return this.acmeFloats;
}
public void setAcmeFloats(final Collection<AcmeFloat> acmeFloats) {
this.acmeFloats = acmeFloats;
}
}
ParadeRepository:
package repositories;
import java.util.Date;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import domain.Parade;
#Repository
public interface ParadeRepository extends JpaRepository<Parade, Integer> {
#Query("select p from Parade p where p.ticker like ?1")
List<Parade> findByTicker(String ticker);
#Query("select p from Parade p where p.moment < ?1 and p.isDraft = false")
List<Parade> findBeforeDate(Date date);
#Query("select p from Parade p where p.isDraft = false")
List<Parade> findAllFinal();
#Query("select p from Parade p where p.isDraft = false and brotherhood.userAccount.id = ?1")
List<Parade> findAllFinalByBrotherhoodAccountId(int id);
#Query("select p from Parade p where brotherhood.userAccount.id = ?1")
List<Parade> findAllByBrotherhoodAccountId(int id);
#Query("select p from Parade p join p.brotherhood.enrolments e where e.member.id= ?1")
List<Parade> findPossibleMemberParades(int id);
}
AcmeFloatRepository:
package repositories;
import java.util.Collection;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import domain.AcmeFloat;
#Repository
public interface AcmeFloatRepository extends JpaRepository<AcmeFloat, Integer> {
#Query("select f from AcmeFloat f where f.brotherhood.userAccount.id = ?1")
Collection<AcmeFloat> findAcmeFloats(int principalId);
}
ParadeService:
package services;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Random;
import javax.validation.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import repositories.ParadeRepository;
import security.LoginService;
import domain.AcmeFloat;
import domain.Parade;
import forms.ParadeForm;
#Service
#Transactional
public class ParadeService {
////////////////////////////////////////////////////////////////////////////////
// Managed repository
#Autowired
private ParadeRepository paradeRepository;
////////////////////////////////////////////////////////////////////////////////
// Supporting services
#Autowired
private BrotherhoodService brotherhoodService;
////////////////////////////////////////////////////////////////////////////////
// Supporting services
#Autowired
private Validator validator;
////////////////////////////////////////////////////////////////////////////////
// Ticker generation fields
private static final String TICKER_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final int TICKER_LENGTH = 5;
private final Random random = new Random();
////////////////////////////////////////////////////////////////////////////////
// Constructors
public ParadeService() {
super();
}
////////////////////////////////////////////////////////////////////////////////
// CRUD methods
public Parade create() {
final Parade parade = new Parade();
parade.setBrotherhood(this.brotherhoodService.findByUserAccountId(LoginService.getPrincipal().getId()));
parade.setAcmeFloats(new ArrayList<AcmeFloat>());
parade.setIsDraft(true);
parade.setDescription("");
parade.setTitle("");
if (parade.getTicker() == null || parade.getTicker().isEmpty()) {
final Calendar calendar = new GregorianCalendar();
String dateString = "";
dateString += String.format("%02d", calendar.get(Calendar.YEAR) % 100);
dateString += String.format("%02d", calendar.get(Calendar.MONTH) + 1);
dateString += String.format("%02d", calendar.get(Calendar.DAY_OF_MONTH));
dateString += "-";
String ticker;
do {
ticker = dateString;
for (int i = 0; i < ParadeService.TICKER_LENGTH; ++i)
ticker += ParadeService.TICKER_ALPHABET.charAt(this.random.nextInt(ParadeService.TICKER_ALPHABET.length()));
} while (this.paradeRepository.findByTicker(ticker).size() > 0);
parade.setTicker(ticker);
}
return parade;
}
public Parade save(final Parade parade) {
Assert.notNull(parade);
//final Parade originalParade = this.paradeRepository.findOne(parade.getId());
//if (originalParade != null)
Assert.isTrue(parade.getIsDraft());
Assert.isTrue(parade.getMoment().after(new Date()));
//TODO: if ticker existe en BBDD, generar nuevo, else, se guarda
return this.paradeRepository.save(parade);
}
public void delete(final Parade parade) {
Assert.notNull(parade);
Assert.isTrue(parade.getIsDraft());
this.paradeRepository.delete(parade);
}
public Parade findOne(final int id) {
return this.paradeRepository.findOne(id);
}
public List<Parade> findAll() {
return this.paradeRepository.findAll();
}
////////////////////////////////////////////////////////////////////////////////
// Ancillary methods
public List<Parade> findWithin30Days() {
final Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DATE, 30);
final Date plus30Days = calendar.getTime();
return this.paradeRepository.findBeforeDate(plus30Days);
}
public List<Parade> findAllByBrotherhoodAccountId(final int id) {
return this.paradeRepository.findAllByBrotherhoodAccountId(id);
}
public List<Parade> findAllFinalByBrotherhoodAccountId(final int id) {
return this.paradeRepository.findAllFinalByBrotherhoodAccountId(id);
}
public List<Parade> findAllFinal() {
return this.paradeRepository.findAllFinal();
}
public List<Parade> findPossibleMemberParades(final int memberId) {
return this.paradeRepository.findPossibleMemberParades(memberId);
}
public Parade reconstruct(final ParadeForm paradeForm, final BindingResult binding) {
Parade result;
if (paradeForm.getId() == 0)
result = this.create();
else
result = this.paradeRepository.findOne(paradeForm.getId());
result.setTitle(paradeForm.getTitle());
result.setDescription(paradeForm.getDescription());
result.setMoment(paradeForm.getMoment());
result.setAcmeFloats(paradeForm.getAcmeFloats());
this.validator.validate(result, binding);
this.paradeRepository.flush();
if (binding.hasErrors())
throw new ValidationException();
return result;
}
}
AcmeFloatService:
package services;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import repositories.AcmeFloatRepository;
import domain.AcmeFloat;
import domain.Parade;
#Service
#Transactional
public class AcmeFloatService {
////////////////////////////////////////////////////////////////////////////////
// Managed repository
#Autowired
private AcmeFloatRepository acmeFloatRepository;
////////////////////////////////////////////////////////////////////////////////
// Supporting services
////////////////////////////////////////////////////////////////////////////////
// Constructors
public AcmeFloatService() {
super();
}
////////////////////////////////////////////////////////////////////////////////
// CRUD methods
public AcmeFloat create() {
final AcmeFloat result = new AcmeFloat();
// set fields
result.setTitle("");
result.setDescription("");
result.setPictures(new ArrayList<String>());
// set relationships
result.setParades(new ArrayList<Parade>());
result.setBrotherhood(null);
return result;
}
public AcmeFloat save(final AcmeFloat acmeFloat) {
Assert.isTrue(acmeFloat != null);
return this.acmeFloatRepository.save(acmeFloat);
}
public Iterable<AcmeFloat> save(final Iterable<AcmeFloat> acmeFloats) {
Assert.isTrue(acmeFloats != null);
return this.acmeFloatRepository.save(acmeFloats);
}
public void delete(final AcmeFloat acmeFloat) {
Assert.isTrue(acmeFloat != null);
this.acmeFloatRepository.delete(acmeFloat);
}
public void delete(final Iterable<AcmeFloat> acmeFloats) {
Assert.isTrue(acmeFloats != null);
this.acmeFloatRepository.delete(acmeFloats);
}
public AcmeFloat findOne(final int id) {
return this.acmeFloatRepository.findOne(id);
}
public List<AcmeFloat> findAll() {
return this.acmeFloatRepository.findAll();
}
////////////////////////////////////////////////////////////////////////////////
// Ancillary methods
public Collection<AcmeFloat> findAcmeFloats(final int id) {
return this.acmeFloatRepository.findAcmeFloats(id);
}
}
ParadeController:
package controllers;
import java.util.Collection;
import javax.validation.Valid;
import javax.validation.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import security.LoginService;
import security.UserAccount;
import services.AcmeFloatService;
import services.BrotherhoodService;
import services.ParadeService;
import domain.AcmeFloat;
import domain.Brotherhood;
import domain.Parade;
import forms.ParadeForm;
#Controller
#RequestMapping("/parade")
public class ParadeController extends AbstractController {
// Services ---------------------------------------------------------------
#Autowired
private ParadeService paradeService;
#Autowired
private BrotherhoodService brotherhoodService;
#Autowired
private AcmeFloatService acmeFloatService;
// Constructors -----------------------------------------------------------
public ParadeController() {
}
// List -------------------------------------------------------------------
#RequestMapping(value = "/brotherhood/list", method = RequestMethod.GET)
public ModelAndView list() {
final ModelAndView result;
Collection<Parade> parades;
parades = this.paradeService.findAllByBrotherhoodAccountId(LoginService.getPrincipal().getId());
result = new ModelAndView("parade/brotherhood/list");
result.addObject("parades", parades);
result.addObject("requestURI", "parade/brotherhood/list.do");
return result;
}
// Create -----------------------------------------------------------------
#RequestMapping(value = "/brotherhood/create", method = RequestMethod.GET)
public ModelAndView create() {
final ModelAndView result;
Parade parade;
parade = this.paradeService.create();
parade.setIsDraft(true);
result = this.createEditModelAndView(parade, "create");
return result;
}
// Edit -------------------------------------------------------------------
#RequestMapping(value = "/brotherhood/edit", method = RequestMethod.GET)
public ModelAndView edit(#RequestParam final int paradeId) {
ModelAndView result;
Parade parade;
parade = this.paradeService.findOne(paradeId);
Assert.notNull(parade);
result = this.createEditModelAndView(parade, "edit");
return result;
}
// Save -------------------------------------------------------------------
#RequestMapping(value = "/brotherhood/edit", method = RequestMethod.POST, params = "save")
public ModelAndView save(#ModelAttribute("parade") final ParadeForm paradeForm, final BindingResult binding) {
ModelAndView result;
Parade parade;
Parade oldParade;
parade = this.paradeService.reconstruct(paradeForm, binding);
oldParade = this.paradeService.findOne(paradeForm.getId());
try {
for(AcmeFloat f : parade.getAcmeFloats()){
Collection<Parade> parades = f.getParades();
parades.add(parade);
f.setParades(parades);
this.acmeFloatService.save(f);
}
if(parade.getId() != 0){
Collection<AcmeFloat> paradesRemoved = oldParade.getAcmeFloats();
paradesRemoved.removeAll(parade.getAcmeFloats());
for(AcmeFloat f : paradesRemoved){
final Collection<Parade> parades = f.getParades();
parades.remove(parade);
f.setParades(parades);
this.acmeFloatService.save(f);
}
}
this.paradeService.save(parade);
result = new ModelAndView("redirect:list.do");
} catch (final ValidationException oops) {
result = this.createEditModelAndView(parade, "edit");
} catch (final Throwable oops) {
result = this.createEditModelAndView(parade, "parade.commit.error", "edit");
}
return result;
}
/*
final Parade paradeUpdated = this.paradeService.reconstruct(paradeForm, binding);
Collection<AcmeFloat> paradesRemoved = new ArrayList<>();
if (paradeForm.getId() != 0)
paradesRemoved = parade.getAcmeFloats();
if (paradeUpdated.getId() != 0)
paradesRemoved.removeAll(paradeUpdated.getAcmeFloats());
final Parade paradeSaved = this.paradeService.save(paradeUpdated);
for (final AcmeFloat f : paradeUpdated.getAcmeFloats()) {
final Collection<Parade> parades = f.getParades();
parades.add(paradeSaved);
f.setParades(parades);
this.acmeFloatService.save(f);
}
if (paradeUpdated.getId() != 0)
for (final AcmeFloat f : paradesRemoved) {
final Collection<Parade> parades = f.getParades();
parades.remove(parade);
f.setParades(parades);
this.acmeFloatService.save(f);
*/
// Delete -----------------------------------------------------------------
#RequestMapping(value = "/brotherhood/edit", method = RequestMethod.POST, params = "delete")
public ModelAndView delete(final Parade parade, final BindingResult binding) {
ModelAndView result;
try {
this.paradeService.delete(parade);
result = new ModelAndView("redirect:list.do");
} catch (final Throwable oops) {
result = this.createEditModelAndView(parade, "parade.commit.error", "edit");
}
return result;
}
// Save in Final Mode -----------------------------------------------------
#RequestMapping(value = "/brotherhood/edit", method = RequestMethod.POST, params = "finalMode")
public ModelAndView finalMode(#Valid final Parade parade, final BindingResult binding) {
ModelAndView result;
if (binding.hasErrors())
result = this.createEditModelAndView(parade, "edit");
else
try {
parade.setIsDraft(false);
this.paradeService.save(parade);
result = new ModelAndView("redirect:list.do");
} catch (final Throwable oops) {
result = this.createEditModelAndView(parade, "parade.commit.error", "edit");
}
return result;
}
// Show -------------------------------------------------------------------
#RequestMapping(value = "/public/show", method = RequestMethod.GET)
public ModelAndView show(#RequestParam final int paradeId) {
ModelAndView result;
Parade parade;
parade = this.paradeService.findOne(paradeId);
Assert.notNull(parade);
Assert.isTrue(parade.getIsDraft());
result = new ModelAndView("parade/public/" + "show");
result.addObject("parade", parade);
// result.addObject("messageCode", null);
return result;
}
// Ancillary Methods ------------------------------------------------------
protected ModelAndView createEditModelAndView(final Parade parade, final String method) {
ModelAndView result;
result = this.createEditModelAndView(parade, null, method);
return result;
}
protected ModelAndView createEditModelAndView(final Parade parade, final String messageCode, final String method) {
final ModelAndView result;
final Brotherhood brotherhood;
final Collection<AcmeFloat> acmeFloats;
final UserAccount userAccount = LoginService.getPrincipal();
brotherhood = this.brotherhoodService.findPrincipal();
acmeFloats = this.acmeFloatService.findAcmeFloats(userAccount.getId());
result = new ModelAndView("parade/brotherhood/" + method);
result.addObject("brotherhood", brotherhood);
result.addObject("acmeFloats", acmeFloats);
result.addObject("parade", parade);
result.addObject("messageCode", messageCode);
return result;
}
}
In the Create case, the flow is the next one: When in the create view after filling form and sending, save() method is called in ParadeController. Its input is a ParadeForm object with id=0. "parade" (the new Parade in this case and the updated Parade in case of edition) and "oldParade" (null in this case but the Parade before the update in update case) objects are created and declared anyway. Then, we go into the try/catch. First, it get the parade's acmeFloats in order to update them adding in their parades collection the just created Parade. But, at first attempt of saving, it throws the following thing:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance
Saving first the new Parade gives the same results. I was intended to, in case it is an edition (so the Parade existed before and can have had AcmeFloats), find the AcmeFloats that have been removed from the Parade and update them and then save the Parade. So I needed the oldParade in edit case to check which AcmeFloats I have to remove the Parade from.
Also, I don't know whether I have to do all this thing with the cascade in #ManyToMany, but just saving the Parade once reconstructed, but it doesn't work anyway, so I decided to post that part of the code so that you figure out how would it work without the cascade.
I've been having troubles with this issue for the last month and before. Thanks in advance.
EDIT 1:
When I put a flush() after saving in the repository, it throws the following exception at saving:
org.springframework.orm.jpa.JpaSystemException: Exception occurred inside getter of domain.Parade.acmeFloats; nested exception is org.hibernate.PropertyAccessException: Exception occurred inside getter of domain.Parade.acmeFloats
My java class is throwing some error. In my class i am using this to get my data.
((myDataDetails) Names.get(0)).InputParamNames().add("SomeValue");
But it is throwing error
Here is my Pohjo Class.
package common.pojo;
import java.util.Date;
import java.util.List;
public class myDataDetails
{
private String myID;
private List<String> InputParamNames;
private List InputParamData;
public String getmyID() {
return this.myID;
}
public void setmyID(String myID) {
this.myID = myID;
}
public List<String> getInputParamNames() {
return this.InputParamNames;
}
public void setInputParamNames(List<String> InputParamNames) {
this.InputParamNames = InputParamNames;
}
public List getInputParamData() {
return this.InputParamData;
}
public void setInputParamData(List InputParamData) {
this.InputParamData = InputParamData;
}
}
What should I need to change in pojo to avoid this exception.
Your class 'myDataDetails' needs to extend from LinkedHashMap in order to cast it.
What you have right now is a regular POJO class that is not an instance of LinkedHashMap, so you can't cast it as such.
EDIT: It should look like this
package common.pojo;
import java.util.Date;
import java.util.List;
import java.util.LinkedHashMap;
public class myDataDetails extends LinkedHashMap<Object, Object>
{
private String myID;
private List<String> InputParamNames;
private List InputParamData;
public String getmyID() {
return this.myID;
}
public void setmyID(String myID) {
this.myID = myID;
}
public List<String> getInputParamNames() {
return this.InputParamNames;
}
public void setInputParamNames(List<String> InputParamNames) {
this.InputParamNames = InputParamNames;
}
public List getInputParamData() {
return this.InputParamData;
}
public void setInputParamData(List InputParamData) {
this.InputParamData = InputParamData;
}
}
Kindly help me to get the subnodes list inside bom attributes
JSON file
[
{
"subConfigId":"bac",
"totalPrice":"634.00",
"bom":{
"ucid":"ucid",
"type":"RootNode",
"attributes":{
"visible":true,
"price_status":"SUCCESS"
},
"subnodes":[
{
"description":"Enterprise Shock Rack",
"ucid":"ucid"
},
{
"description":"SVC",
"ucid":"ucid"
}
]
},
"breakdown":{
"SV":550.0,
"HW":6084.0
},
"currency":"USD"
}
]
GsonNodes.java
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class GsonNodes {
public static void main(String[] args) throws IOException {
try{
JsonElement je = new JsonParser().parse(new FileReader(
"C:/Desktop/json.txt"));
JsonArray ja = je.getAsJsonArray();
Iterator itr = ja.iterator();
while(itr.hasNext()){
JsonElement je1 = (JsonElement) itr.next();
Gson gson = new Gson();
Details details = gson.fromJson(je1, Details.class);
System.out.println(details.getSubConfigId());
System.out.println(details.getCurrency());
System.out.println(details.getBreakdown());
System.out.println(details.getTotalPrice());
System.out.println(details.getBom().getUcid());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Details.java POJO
import java.io.Serializable;
import java.util.Map;
public class Details implements Serializable{
private String subConfigId;
private String totalPrice;
private Bom bom;
private String currency;
private Map<String, String> breakdown;
public String getSubConfigId() {
return subConfigId;
}
public void setSubConfigId(String subConfigId) {
this.subConfigId = subConfigId;
}
public String getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(String totalPrice) {
this.totalPrice = totalPrice;
}
public Bom getBom() {
return bom;
}
public void setBom(Bom bom) {
this.bom = bom;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public Map<String, String> getBreakdown() {
return breakdown;
}
public void setBreakdown(Map<String, String> breakdown) {
this.breakdown = breakdown;
}
}
Bom.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Bom implements Serializable{
private String ucid;
private String type;
private Map<String, String> attributes;
private List<Subnodes> subnodes = new ArrayList<Subnodes>();
public String getUcid() {
return ucid;
}
public void setUcid(String ucid) {
this.ucid = ucid;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
#Override
public String toString(){
return getUcid() + ", "+getType()+", "+getAttributes();
}
}
Subnodes.java
import java.io.Serializable;
import java.util.Map;
public class Subnodes implements Serializable{
private String description;
private String ucid;
private Map<String, String> attributes;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUcid() {
return ucid;
}
public void setUcid(String ucid) {
this.ucid = ucid;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
}
I am getting an error , when i try to get the "subnodes"
I added the following code in the class
private List<Subnodes> subnodes = new ArrayList<Subnodes>();
then i am getting the error "Expected STRING but was BEGIN_ARRAY"
kindly help me that how can i get the "subnodes" list
In Bom.java
Please add a getter/setter method for :
private List<Subnodes> subnodes = new ArrayList<Subnodes>();
public List<Subnodes> getSubnodes() {
return subnodes;
}
public void setSubnodes(List<Subnodes> subnodes) {
this.subnodes = subnodes;
}
i have tried as below .. this is working fine.
package com.brp.mvc.util;
import java.io.IOException;
import java.util.Iterator;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class GsonNodes {
public static void main(String[] args) throws IOException {
try {
JsonElement je = new JsonParser().parse("[{\"subConfigId\":\"bac\",\"totalPrice\":\"634.00\",\"bom\":{\"ucid\":\"ucid\",\"type\":\"RootNode\",\"attributes\":{\"visible\":true,\"price_status\":\"SUCCESS\"},\"subnodes\":[{\"description\":\"Enterprise Shock Rack\",\"ucid\":\"ucid\"},{\"description\":\"SVC\",\"ucid\":\"ucid\"}]},\"breakdown\":{\"SV\":550.0,\"HW\":6084.0},\"currency\":\"USD\"}]");
JsonArray ja = je.getAsJsonArray();
Iterator itr = ja.iterator();
while (itr.hasNext()) {
JsonElement je1 = (JsonElement) itr.next();
Gson gson = new Gson();
Details details = gson.fromJson(je1, Details.class);
System.out.println(details.getSubConfigId());
System.out.println(details.getCurrency());
System.out.println(details.getBreakdown());
System.out.println(details.getTotalPrice());
System.out.println(details.getBom().getUcid());
System.out.println(details.getBom().getSubnodes().get(0).getDescription());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
i have added one method to convert json into string as below :
public static String readFile(String filename) {
String result = "";
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
line = br.readLine();
}
result = sb.toString();
} catch(Exception e) {
e.printStackTrace();
}
return result;
}
and use this method like below :
JsonElement je = new JsonParser().parse(readFile("C:/Desktop/json.txt"));