Spring MVC NumberFormatException

0

Przy zwracaniu danych do widoku mam podany niżej błąd. Mógłby ktoś coś poradzić?

@Entity
    @Table(name="Product")
    public class Product {
        @Id
        @GeneratedValue
        private int idProduct;
        private String status;
        private String name;
    @OneToMany(mappedBy = "product")
        private List <Repository> repository;

    @Entity
    @Table(name="Repository")
    public class Repository {

        @Id
        private int idRepository;
        private int quantity;
        private double unitPrice;

        @ManyToOne
        private Product product;

view:

<c:forEach items="${products.repository}" var="product">
                            <p>${product.unitPrice}</p>
                            </c:forEach>
 

ERROR:

 
java.lang.NumberFormatException: For input string: "repository"

i drugie pytanie, jak zrobić żeby pętla w widoku obracała się wybraną ilość razy? Przykładowo jak chciałbym wyciągnąć tylko pierwszy obiekt listy

0
  1. Błąd jest w ZUPEŁNIE INNYM MIEJSCU niż kod który nam pokazałeś. Gdzie? Przeanalizuj stacktrace.
  2. Wrzuć do widoku listę obciętą. Widok ma TYLKO wypisywać to co dostanie z backendu. Wszelkie operacje na danych wykonuje sie po stronie serwera!
0

Jak mam to wykonać po stronie backendu, jeśli w widoku wszystkie dane wyciągam z obiektu typu Product?

0

Nie powinieneś w ogóle przesyłać i przetwarzać gdzieś obiektów encyjnych. Powinieneś tworzyć niemutowane obiekty DTO przechowujące TYLKO te dane którymi jesteś zainteresowany i w warstwie serwisów dokonywać translacji encji pobranych z DAO do formatu DTO który jest potrzebny w widoku.

0

Czy utworzenie takiego DAO jest KONIECZNE do korzystania z usług REST-owych i Ajax?

0

Nie, ale równie dobrze można też napisać cały kod w jednej wielkiej funkcji main() ;]

0
Shalom napisał(a):

Nie powinieneś w ogóle przesyłać i przetwarzać gdzieś obiektów encyjnych. Powinieneś tworzyć niemutowane obiekty DTO przechowujące TYLKO te dane którymi jesteś zainteresowany i w warstwie serwisów dokonywać translacji encji pobranych z DAO do formatu DTO który jest potrzebny w widoku.

Dlaczego? Przed jakimi sytuacjami to zabezpiecza?

1

@InterruptedException na przykład przed tym że ktoś podciągnie ci @Transactional gdzieś wyżej a ty będziesz sobie majstrował przy obiektach wyciągniętych z bazy myśląc że są już "odpięte" i nagle się okaże że z bazy znikają ci dane nie wiadomo gdzie (tak, widziałem taki problem w dość sporym projekcie ;]). Albo że przypadkiem dociągasz sobie jakieś dowiązania Lazy generując miliony zapytań do bazy (taki problem też widziałem, ma nawet swoją nazwę n+1 select problem).

Poza tym tak generalnie to ułatwia testowanie i modyfikowanie systemu bo kolejne warstwy systemu zależą tylko od pewnego genralnego interfejsu. Dzięki takiemu podejściu możesz całkowicie przebudować warstwę DAO i nie martwić sie tym że Widok albo Serwisy polegają gdzieś na twoich klasach encyjnych (których teraz wcale nie chcesz na przykład mieć).

0

Piszę złożoną aplikację z wykorzystaniem Ajax i usług REST i mam następujący problem.

Wyświetlam sobie pozycje w koszyku na stronie za pomocą dyrektywy AngularJS, jednak pętla nie obraca się ani razu. Wygląda to tak że Mapa cartItems jest po prostu pusta.
.jsp

 
<tr ng-repeat="item in cart.cartItems">
					<td>{{item.product.productId}}-{{item.product.name}}</td>

JavaScript - metoda kontrolera interfejsu użytkownika:

 
  $scope.addToCart = function(productId) {
		  						$http.put('/webstore/rest/cart/add/'+productId)
		  						 	 .success(function(data) {
		  						 		 		$scope.refreshCart($http.get('/webstore/rest/cart/get/cartId'));
		  						 		 		alert("Produkt pomyślnie dodany do koszyka!");
		  						 	 		});
		  					};

CartRestController:

 
@RequestMapping(value = "/add/{productId}", method = RequestMethod.PUT)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void addItem(@PathVariable String productId, HttpServletRequest request) {
		
		String sessionId = request.getSession(true).getId();
		Cart cart = cartService.read(sessionId);
		if(cart== null) {
			cart = cartService.create(new Cart(sessionId));
		}
		
	     int pom=Integer.valueOf(productId);
		Produkt product = productService.findByidProdukt(pom);
		
		cart.addCartItem(new CartItem(product));
		
		cartService.update(sessionId, cart);
	}

Cart:

 
public void addCartItem(CartItem item) {
		String productId = String.valueOf(item.getProduct().getIdProdukt());
		
		if(cartItems.containsKey(productId)) {
			CartItem existingCartItem = cartItems.get(productId);
			existingCartItem.setQuantity(existingCartItem.getQuantity()+item.getQuantity());
			cartItems.put(productId, existingCartItem);
		}
		else {
			cartItems.put(productId, item);
		}
		
		updateGrandTotal();	
	}

CartItem:

public class CartItem {
	
	private Produkt product;
	private int quantity;
	private BigDecimal totalPrice; 
	
	public CartItem() {
		
	}
	public CartItem(Produkt product) {
		super();
		this.product=product;
		this.quantity=1;
		this.totalPrice = product.getUnitPrice;
	}
 

Zdaję sobie sprawę że ciężko jest dostrzec tutaj błąd no ale długo się z tym męczę dlatego postanowiłem to wrzucić na form. Próbowałem użyć debuggera ale marne wnioski z tego. Jakby ktoś zechciał przeanalizować kod i mi coś podpowiedzieć to będę niezwykle wdzięczny.

0

Ten exception wyrzucany jest gdy następuje próba przekonwertowania Stringa na Int'a. Poszukaj w kodzie wyrażeń typu Integer.ValueOf(),a przede wszystkim Przeanalizuj (możesz również wrzucić tutaj) stacktrace - tam będzie odpowiedź gdzie wystąpił błąd.

0

@marekk527 trudno zobaczyć błąd skoro pokazujesz ZUPEŁNIE INNY KOD niż ten z którym masz problem. Jak debugujesz ten fragment to mnie nie dziwi że nic nie znalazłeś.

Piszę złożoną aplikację z wykorzystaniem Ajax i usług REST

Zapomnij. Jeszcze długa droga przed tobą bo teraz to można powiedzieć że co najwyżej sklejasz losowe kawałki kodu z internetu i modlisz się zeby coś zadziałało.

Zapnij debugger w metodzie kontrolera który pobiera dane z bazy i przesyła je do widoku w którym ci sie nie wyświetlają. Będziesz wtedy widział czy z bazy cokolwiek się pobrało.

0

<td>{{item.product.productId}}-{{item.product.name}}</td>

Przyjrzałbym się temu. Nie jestem pewny ale wydaje mi się że jeżeli korzystasz z EL w taki sposób to wyrażenie item.product.name zostanie przekonwertowane na liczbę. Wynika to z tego że wcześniej masz znak "-". Zakładałem że chciałeś wyświetlić znak "-" a nie odejmować. Zamień to na:
<td>${item.product.productId}-${item.product.name}</td>
i daj znać

0

Dlaczego cart.cartItems jest puste i nic mi się na stronie nie wyświetla?

Cart.jsp

 
	<tr ng-repeat="item in cart.cartItems">
					<td>{{item.product.idProdukt}}-{{item.product.nazwa}}</td>
					<td>{{item.quantity}}</td>
					<td>{{item.quantity}}</td>
				</tr>

CartItem.java

 
public class CartItem {
	
	private Produkt product;
	private int quantity;
	private BigDecimal totalPrice; 
	
	public CartItem() {
		
	}
	public CartItem(Produkt product) {
		super();
		this.product=product;
		this.quantity=1;
		this.totalPrice = BigDecimal.valueOf(product.Magazyn().get(0).getCena());
	}
	public Produkt getProduct() {
		return product;
	}
	public void setProduct(Produkt product) {
		this.product = product;
		this.updateTotalPrice();
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
		this.updateTotalPrice();
	}
	public BigDecimal getTotalPrice() {
		return totalPrice;
	}
	public void updateTotalPrice() {
		
		totalPrice = BigDecimal.valueOf(product.Magazyn().get(0).getCena()).multiply(new BigDecimal(this.quantity));
	}

Cart.java

 
public class Cart {
	private String cartId;
	private Map<String,CartItem> cartItems;
	private BigDecimal grandTotal;
	
	public Cart(){
		cartItems = new HashMap<String, CartItem>();
		grandTotal = new BigDecimal(0);
	}
	
	public Cart(String cartId) {
		this();
		this.cartId = cartId;
	}

	public String getCartId() {
		return cartId;
	}

	public void setCartId(String cartId) {
		this.cartId = cartId;
	}

	public Map<String, CartItem> getCartItems() {
		return cartItems;
	}

	public void setCartItems(Map<String, CartItem> cartItems) {
		this.cartItems = cartItems;
	}

	public BigDecimal getGrandTotal() {
		return grandTotal;
	}

	public void addCartItem(CartItem item) {
		String productId = String.valueOf(item.getProduct().getIdProdukt());
		
		if(cartItems.containsKey(productId)) {
			CartItem existingCartItem = cartItems.get(productId);
			existingCartItem.setQuantity(existingCartItem.getQuantity()+item.getQuantity());
			cartItems.put(productId, existingCartItem);
		}
		else {
			cartItems.put(productId, item);
		}
		
		updateGrandTotal();	
	}
	
	public void updateGrandTotal() {
		grandTotal = new BigDecimal(0);
		for(CartItem item : cartItems.values()) {
			grandTotal = grandTotal.add(item.getTotalPrice());
		}
	}

CartRepository.java

@Repository
public class InMemoryCartRepository implements CartRepository{
	
	private Map<String, Cart> listOfCarts;
	

	public InMemoryCartRepository() {
		listOfCarts = new HashMap<String,Cart>();
		
	}
	
	
	public Cart create(Cart cart) {
		if(listOfCarts.keySet().contains(cart.getCartId())) {
			throw new IllegalArgumentException(String.format("Nie można utworzyć koszyka. Koszyk o wskazanym  id (%) już istnieje.",cart.getCartId()));
		}

		listOfCarts.put(cart.getCartId(), cart);
		return cart;
	}
	
	
	public Cart read(String cartId) {
		return listOfCarts.get(cartId);
	}

	public void update(String cartId, Cart cart) {
		if(!listOfCarts.keySet().contains(cartId)) {
			throw new IllegalArgumentException(String.format("Nie można zaktualizować koszyka. Koszyk o wskazanym id (%) nie istnieje.",cartId));
		}

		listOfCarts.put(cartId, cart);
	}

}

CartRestController.java

@Controller
@RequestMapping(value = "rest/cart")
public class CartRestController {

	@Autowired
	private CartService cartService;
	
	@Autowired
	private ProduktService productService;
	
	@RequestMapping(method = RequestMethod.POST)
	public @ResponseBody Cart create(@RequestBody Cart cart) {
		return  cartService.create(cart);
	}

	@RequestMapping(value = "/{cartId}", method = RequestMethod.GET)
	public @ResponseBody Cart read(@PathVariable(value = "cartId") String cartId) {
		return cartService.read(cartId);
	}

	@RequestMapping(value = "/{cartId}", method = RequestMethod.PUT)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void update(@PathVariable(value = "cartId") String cartId,	@RequestBody Cart cart) {
		cartService.update(cartId, cart);
	}

	@RequestMapping(value = "/{cartId}", method = RequestMethod.DELETE)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void delete(@PathVariable(value = "cartId") String cartId) {
		cartService.delete(cartId);
	}
	
	@RequestMapping(value = "/add/{productId}", method = RequestMethod.PUT)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void addItem(@PathVariable String productId, HttpServletRequest request) {
		
		String sessionId = request.getSession(true).getId();
		Cart cart = cartService.read(sessionId);
		if(cart== null) {
			cart = cartService.create(new Cart(sessionId));
		}
		
	     int pom=Integer.valueOf(productId);
		Produkt product = productService.findByidProdukt(pom);
		
		cart.addCartItem(new CartItem(product));
		
		cartService.update(sessionId, cart);
	}
	
	@RequestMapping(value = "/remove/{productId}", method = RequestMethod.PUT)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void removeItem(@PathVariable String productId, HttpServletRequest request) {
		
		String sessionId = request.getSession(true).getId();
		Cart cart = cartService.read(sessionId);
		if(cart== null) {
			cart = cartService.create(new Cart(sessionId));
		}
		
		
		 int pom=Integer.valueOf(productId);
			Produkt product = productService.findByidProdukt(pom);
		
		cart.removeCartItem(new CartItem(product));
		
		cartService.update(sessionId, cart);
	}
0

Brak mi słów po prostu. To mój ostatni post w twoich wątkach bo mówi sie do ciebie jak do ściany. Zapnij debugger tam gdzie dodajesz rzeczy do koszyka i tam gdzie je wyciągasz. Możesz to zrobić nawet na poziomie tego swojego repozytorium a następnie zobacz co się dzieje jak próbujesz coś dodać albo pobrać z "bazy". Jeśli na tym poziomie wszystko się dodaje / pobiera to patrzysz "wyżej" i szukasz miejsca gdzie się psuje. Jeśli z kontrolera do widoku wychodzi ładna pełna kolecja a widok nic nie wyświetla to błąd jest w widoku.

0

Z debbugera wynika że zarówno:

cart.addCartItem(new CartItem(product))

jak i cartItems.put(productId, item)

 działają poprawnie
0

Tutaj wrzucam skany z debuggera z metodami przy których je wywoływałem , według mnie wszystko jest tak jak być powinno. Widok też jest chyba ok.To dlaczego to nie działa? Bardzo proszę o pomoc.

controllers.js - działa prawidłowo bo testowałem

Dodałem sobie do testów w CartController coś takiego:

 model.addAttribute("koszyki",cartRepository.listOfCarts()); 

A w widoku cart.jsp coś takiego:

 <c:forEach items="${koszyki}" var="product">
          <p>CartId: ${product.value.cartId} </p>
          <p>Cena: ${product.value.grandTotal}</p>
          <c:forEach items="${koszyki.cartItems}" var="a">
           ilość: ${a.quantity}
          </c:forEach>
          </c:forEach>

I z tego mam DIAGNOZĘ taką, że cartItems jest nullem, tylko gdzie mam błąd??

Czy jest jakaś możliwość żebym miał źle coś skonfigurowane w serwlecie przekazującym bądź zależnościach Mavena?
Czy ma to jakieś znaczenie, że dane (product) wczytuje z bazy danych?

Jak to jest w ogóle możliwe że moje cartItems jest puste, jeśli w tym miejscu:

public void addCartItem(CartItem item) {
		String productId = String.valueOf(item.getProduct().getIdProdukt());
		
		if(cartItems.containsKey(productId)) {
			CartItem existingCartItem = cartItems.get(productId);
			existingCartItem.setQuantity(existingCartItem.getQuantity()+ item.getQuantity());
			cartItems.put(productId, existingCartItem);
		} else {
			cartItems.put(productId, item);   // dodawanie produktu do cartItems
		}
		updateGrandTotal();
	} 

w debuggerze mam wyraźnie dodawany produkt tam?

0

co ciekawe, jeśli nie łączę się z bazą danych, a tworze sobie klasę InMemoryProductRepository będącą repozytorium produktów to cartItems wyświetlają się:

 

@Repository
public class InMemoryProductRepository implements ProductRepository{
	
	private List<Product> listOfProducts = new ArrayList<Product>();
	
	public InMemoryProductRepository() {
		Product iphone = new Product("P1234","iPhone 5s", new BigDecimal(500));
	    iphone.setDescription("Apple iPhone 5s, smartfon z 4-calowym ekranem o rozdzielczości 640×1136 i 8-megapikselowym aparatem");
	    iphone.setCategory("smartfon");

	    Product laptop_dell = new Product("P1235","Dell Inspiron", new BigDecimal(700));
	    laptop_dell.setDescription("Dell Inspiron, 14-calowy laptop (czarny) z procesorami Intel Core 3. generacji");
	    laptop_dell.setCategory("laptop");

	    listOfProducts.add(iphone);
	    listOfProducts.add(laptop_dell);

	}

	public List<Product> getAllProducts() {
		return listOfProducts;
	}
0

Mógłby ktoś mi pomoć? Męczę się z tym już dosyć długo...

0

@marek527 popatrzyłem na źródła które mi wysłałeś i moje wnioski:

  1. Idę o zakład że nie masz pojęcia co robi 75% tego kodu. Wątpie zebyś umiał zrobić prostego CRUDa w Spring MVC a co dopiero z RESTem i Angularem. Kod wygląda na jakiś sklejany random albo bezmyślnie przepisany.
  2. Oczywiście wysłałeś mi działającą wersje, to z repozytoriami in-memory. Spróbowałem przepiąć sie na repozytoria Spring-Data ale taka konfiguracja w ogóle nie działa, bo nie poprawiłes błędów o których pisaliśmy wczesniej - nadal masz niedopasowane wersje bibliotek.
  3. Wrzucasz tam Spring 4.X a jednocześnie kod wygląda na czasy Springa 2.5.X. Niby masz tam JPA a jednak używasz Providera z org.hibernate.ejb (deprecated ofc).

O tym że wysłałeś projekt skonfigurowany pod jakąś swoją bazę zamiast dać tam jakieś H2, żeby ktoś mógł sobie jednym klikiem odpalić bez potrzeby grzebania w konfiguracji to nawet nie wspominam, tak samo o hardkodowanych ścieżkach przewidujących pod jaką nazwą ktoś będzie deployował ten projekt (a jak ktoś da co innego niż /webstore to co? po co w ogóle to hardkodowałes? o_O).

Ogólnie Nie polecam tego allegrowicza.

@marek527 zalecam naukę OD PODSTAW tak żebyś ROZUMIAŁ kod który masz w projekcie. Do tego sklepu możesz wrócic za jakieś 3-6 miesięcy nauki. Przy czym przypuszczam że złapiesz sie wtedy za głowę i zrobisz kill it with fire a potem napiszesz to od nowa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1