简体   繁体   中英

java - Autowiring Repository in class that is instantiated in Spring Boot

So I have an API client type class right now, which I am trying to connect to my repository so that I can store data in the MySQL database.

The problem I'm having is that the API client class instantiates a new object of itself, so the Autowiring doesn't work correctly. I've looked around for a workaround for this problem, and I've seen a couple options, but I'm confused on how to apply them to my problem.

For reference, here are parts of some of the relevant files:

GeniusApiClient.java:

@Component
public final class GeniusApiClient {
    private final OkHttpClient client = new OkHttpClient();

    @Autowired
    private ArtistDao artistDao;

    public static void main(String[] args) throws Exception {
        GeniusApiClient geniusApiClient = new GeniusApiClient();
        String artistId = (geniusApiClient.getArtistId("Ugly Duckling"));

        ArrayList<String> artistSongIds = geniusApiClient.getArtistSongIds(artistId);
        System.out.println(geniusApiClient.getAllSongAnnotations(artistSongIds, artistId));
    }

    public String getAllSongAnnotations(ArrayList<String> songIds, String artistId) {
        Artist artist = new Artist("test name for now", "string123", "223");
        artistDao.save(artist);
        return "finished";
    }

}

ArtistDao.java:

@Transactional
public interface ArtistDao extends CrudRepository<Artist, Long> {
    public Artist findByGeniusId(String geniusId);
}

ArtistController.java:

@Controller
public class ArtistController {
    @Autowired
    private ArtistDao artistDao;

    /**
     * GET /create  --> Create a new artist and save it in the database.
     */
    @RequestMapping("/create")
    @ResponseBody
    public String create(String name, String annotations, String genius_id) {
        String userId = "";
        try {
            genius_id = genius_id.replaceAll("/$", "");
            Artist artist = new Artist(name, annotations, genius_id);
            artistDao.save(artist);
            userId = String.valueOf(artist.getId());
        }
        catch (Exception ex) {
            return "Error creating the artist: " + ex.toString();
        }
        return "User succesfully created with id = " + userId;
    }

   /**
     * GET /get-by-email  --> Return the id for the user having the passed
     * email.
     */
    @RequestMapping("/get")
    @ResponseBody
    public String getByEmail(String genius_id) {
        String artistId = "";
        try {
            Artist artist = artistDao.findByGeniusId(genius_id);
            artistId = String.valueOf(artist.getId());
        }
        catch (Exception ex) {
            return "User not found";
        }
        return "The user id is: " + artistId;
    }

}

The problem is that in GeniusApiClient.java in the getAllSongAnnotations method, I have a null pointer exception when I try and access the artistDao. I understand that my instantiation of this class is what is messing up the Autowiring, but I'm curious on what the best way to go about fixing this might be.

I considered making all of my methods in the class static so that I wouldn't have to instantiate a new method, but I don't think this would work very well. Any suggestions?

Thanks

EDIT:

Removed some irrelevant code for clarity.

EDIT2:

Added ArtistController.java

To be able to autowire/inject an object, that object must be a Spring bean.

Here you can't autowire ArtistDao because it's not a bean. There are several annotation options to make it bean but the one suits in this case is @Repository annotation. It's just a specialized version of @Component which you used in GeniusApiClient class.

So,

@Repository
@Transactional
public interface ArtistDao extends CrudRepository<Artist, Long> {
    public Artist findByGeniusId(String geniusId);
}

should work.

I'd suggest you to read: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html

If reading reference documentation sounds scary to you, you can also take a look at Core Spring part of Spring in Action .

Don't make GeniusApiClient.class final. Spring will use CGLIB to dynamically extend your class in order to make a proxy. And the requirement for CGLIB to work is to have your classes non-final.

More on this here: Make Spring Service Classes Final?

您在catch块中尝试执行的操作对我来说还不清楚,您必须更正该错误,并用所需的操作替换该错误,以便在发生任何异常情况时采取措施。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM