Konfiguracja Spring MVC od podstaw, błąd 404

0

Ostatnio w celach dydaktycznych chciałem sobie stworzyć od zupełnych podstaw projekt używający Springa. Zacząłem zabawę od Spring MVC, ale nie chciałem korzystać ze Spring Boot czy Spring initializr. Stworzyłem pom.xml, strukture katalogów, pliki konfiguracji (chcę konfigurować projekt w Javie, nie xmlem). Dodałem prosty kontroler. Niestety, po wygenerowaniu artefaktu i wrzuceniu go do Tomcata dostaję 404 na http://localhost:{port}/

Adres repozytorium: https://github.com/lukasz-gosiewski/springtest

Czy ktoś wie może gdzie leży problem ?

1

Spróbuj http://localhost:{port}/{nazwa_pliku_war}/

0

Masz ustawione skanowanie złego pakietu. Jak już kopiujesz kod, to ze zrozumieniem. W projekcie masz tylko pakiet config a jednak skanujesz pl.test.springtest. Ciekawe jak Spring miałby w takim wypadku znaleźć ten twój kontroler...

Poza tym jeśli chcesz to zrobić "bez boota" to ci brakuje w tym projekcie trochę... ;] To wygląda jakbyś wziął aplikacje ze Spring Boota a potem go wywalił z zależości licząc że to będzie miało ręce i nogi, a nie będzie. Maven też ci nie zbuduje ot tak poprawnego wara sam z siebie. Boot takie rzeczy dodaje od "siebie", ale jak go nie używasz to musisz to zrobić ręcznie.

Popatrz troche na https://github.com/Pharisaeus/SpringScaffoldApplication wiem że tam jednak jest trochę XMLa, ale możesz sobie z tego wystartować i zmieniać konfiguracje na javę.

0

@Shalom: Nic nie kopiuje więc twoje docinki sobie daruj, a co do skanowania pakietu to po prostu wynik eksperymentów bo też pierwsze co obstawiałem to niepoprawny pakiet w skanowaniu. Nie liczę na to że coś mi samo zbuduje wara, robię to ręcznie. Ręcznie też deployuję wara na tomcata. Problem polega na tym że Spring najwyraźniej kompletnie nie widzi mojego kontrolera, co by potwierdzało błędne skanowanie pakietów.

Czego konkretnie mi brakuje w projekcie? Jest to całkiem możliwe, robię to pierwszy razw takiej formie, do tej pory zawsze używałem XMLi.

@slepy Niestety, tego też próbowałem - bez efektów.

0

Po pierwsze pom.xml dla aplikacji web jest nie jest kompletny. Po drugie musisz poinformować springa gdzie ma szukac klas z adnotacjami

         AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation("eu.its.web");

Plik pom wygenerowany przez netbeanse dla aplikacji web z dodanymi zależnościami na potrzeby twojej aplikacji:

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>pl.arek</groupId>
    <artifactId>Web</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>Web</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0-b01</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Usuń adnotacje ComponentScan ze swoich klas i powinno działać. Oczywiście możesz rozdzielić konfigurację i w przykladzie wyżej podać lokalizację tylko jakiejś klasy konfiguracyjnej i tam konfigurować albo przez tworznie beanow albo dalej adnotacji.

Pozdrawiam

0

@SkromnyKrawiec .setConfigLocation używałem, nie pomagało - dodatkowo źródła mówią, że używa defaultowej jeśli nie ustawisz innej i też powinno wtedy działać. Reszta twojego poma dodaje tylko info do budowania artefaktu, co robię i tak sam. W jakim celu dodajesz javaee web api i w czemu mam usunac setComponentScan ?

0

Wspomniałem o usunięciu tych adnotacji dlatego że jak użyjesz setConfigLocation to nie ma później potrzeby skanowania tych paczek jeszcze raz. Chyba że w setConfigLocation podasz tylko paczkę gdzie znajduje sie twoja konfiguracja to później w konfiguracji znów będziesz musiał w jakiś sposób powiedz springowi gdzie ma szukać reszty beanow czyli kontrolerow etc. po prostu zadbaj o to żeby każda paczka była przeskanowana tylko raz pomoże ci to uniknąć problemów z dostarczeniem kilku takich samych beanow co owocuje błędami. Po wprowadzonych modyfikacjach które ci opisałem wcześniej twój kod dziala. Dlaczego chcesz ręcznie budować wara ? nie rozumiem, skoro masz narzędzia do tego ?

Pozdrawiam

0

@Skromny Krawiec Konkretnie która modyfikacja sprawiła że projekt Ci zadziałał ? Chcę to zrobić ręcznie bo lubię wiedzieć co się pod spodem dzieje. To nie jest projekt potrzebny na jutro, normalnie po prostu szukałbym w sieci, ale okazało się że jest zaskakująco ubogo jeśli chodzi o java config bez boota.

1

poma już masz więc

 package pl.arek.web.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

}

tu chyba się nic nie zmieniło

 package pl.arek.web;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;


public class AppInitializer implements WebApplicationInitializer {

    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation("pl.arek.web");

        servletContext.addListener(new ContextLoaderListener(context));
        ServletRegistration.Dynamic dispatcher = servletContext.
                addServlet("DispatcherServlet", new DispatcherServlet(context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

}

ale tak naprawde powinienes tu raczej podac paczke gdzie znajduje się tylko konfiguracja a pozniej za pomoca np @ComponentScan dodac kolejne mapowanie ale w tak by nie zawieralo już tych przeskanowanych paczek. Tak czy inaczej w taki prostacki sposob też działa. Jak pobrałem twoj kod to bez setConfigLocation spring nie odnajdywał twoich klas konfiguracyjnych.

 package pl.arek.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    @ResponseBody
    public String showIndex() {
        return "hello world";
    }
}

reszte plikow wywaliłem bo nie byla potrzebna.

Pozdrawiam

0

@Skromny Krawiec Super! Tak myślałem że nie skanuje odpowiednich pakietów. Teraz zreztą nadal nie skanuje ale przynajmniej wiem gdzie szukać problemu. A jesteś może w stanie wyjaśnić mi plik pom.xml który wysłałeś ? Które rzeczy są absolutnie niezbędne i które co dokładnie robią ? Rozumiem że to sporo pisania i wiedzy, ale jeśli nie to może chociaż odeślesz do jakiegoś dobrego źródła ? Dzięki !

0

A tak btw. to http://www.mkyong.com/spring3/spring-3-mvc-hello-world-example-annotation/ drugi link z googla :)

Pozdrawiam

0

Wyrzuciłem trochę rzeczy z twojego configu, nadal działa. Dodatkowo stworzyłem pakiet pl.test.springtest bo najwyraźniej z jakiegoś powodu go nie było. Teraz interesuje mnie tylko ten fragment poma, bo ewidentnie konfiguruje on proces budowania artefaktu war i chciałbym wiedzieć dokładnie co on robi i jak.

 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
0

Udało mi się usunąć kolejne części tej konfiguracji bez psucia projektu. Zmiany na repo. Dodatkowo gdyby ktoś szukał informacji o sekcji build to tu jest sporo https://www.tutorialspoint.com/maven/maven_plugins.htm

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