Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Java Spring with Hibernate File Uploads and Entity Updates in Spring + Hibernate Persisting a GIF From the Controller

Hexadecimal string with odd number of characters

When I try to upload a gif, I get the following error code:

org.h2.jdbc.JdbcSQLException: Hexadecimal string with odd number of characters: "2016-08-06 23:39:06.423"; SQL statement:
insert into Gif (id, bytes, category_id, dateUploaded, description, favorite, hash, username) values (null, ?, ?, ?, ?, ?, ?, ?) -- (NULL, ?1, ?2, ?3, ?4, ?5, ?6, ?7) [90003-191]

Does anyone know how this could be fixed? I'll attach the relevant code (doesn't contain entirety of classes):

GifDAO Implementation:

@Repository
public class GifDAOImpl implements GifDao{
    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public List<Gif> findAll() {
        Session session = sessionFactory.openSession();
        CriteriaBuilder builder = session.getCriteriaBuilder();
        CriteriaQuery<Gif> criteria = builder.createQuery(Gif.class);
        criteria.from(Gif.class);
        List<Gif> gifs = session.createQuery(criteria).getResultList();
        session.close();
        return gifs;
    }

    @Override
    public Gif findById(Long id) {
        Session session = sessionFactory.openSession();
        Gif gif = session.get(Gif.class,id);
        session.close();
        return gif;
    }

    @Override
    public void save(Gif gif) {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        session.save(gif);
        session.getTransaction().commit();
        session.close();
    }

GifService Implentation:

@Service
public class GifServiceImpl implements GifService {
    @Autowired
    private GifDao gifDao;

    @Override
    public List<Gif> findAll() {
        return gifDao.findAll();
    }

    @Override
    public Gif findById(Long id) {
        return gifDao.findById(id);
    }

    @Override
    public void save(Gif gif, MultipartFile file) {
        try {
            gif.setBytes(file.getBytes());
            gifDao.save(gif);
        } catch (IOException e) {
            System.err.println("Unable to get byte array from uploaded file.");
        }
    }

GifController:

    // Single GIF page
    @RequestMapping("/gifs/{gifId}")
    public String gifDetails(@PathVariable Long gifId, Model model) {
        // TODO: Get gif whose id is gifId
        Gif gif = gifService.findById(gifId);

        model.addAttribute("gif", gif);
        return "gif/details";
    }

    // GIF image data
    @RequestMapping("/gifs/{gifId}.gif")
    @ResponseBody
    public byte[] gifImage(@PathVariable Long gifId) {
        // TODO: Return image data as byte array of the GIF whose id is gifId
        return gifService.findById(gifId).getBytes();
    }

    // Upload a new GIF
    @RequestMapping(value = "/gifs", method = RequestMethod.POST)
    public String addGif(@RequestParam MultipartFile file, Gif gif, RedirectAttributes attributes) {
        // TODO: Upload new GIF if data is valid
        gifService.save(gif, file);
        attributes.addFlashAttribute("flash",new FlashMessage("GIF successfully uploaded", FlashMessage.Status.SUCCESS));

        // TODO: Redirect browser to new GIF's detail view
        return String.format("redirect:/gifs/%s",gif.getId());
    }

Gif form:

<form th:object="${gif}" enctype="multipart/form-data" th:action="@{/gifs}" method="post">
        <div class="row">
            <div class="col s12 l8">
                <div class="file-wrapper">
                    <input type="file" id="file" name="file"/>
                    <span class="placeholder" data-placeholder="Choose an image...">Choose an image...</span>
                    <label for="file" class="button">Browse</label>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col s12 l8">
                <input type="text" th:field="*{description}" placeholder="Description"/>
            </div>
        </div>
        <div class="row">
            <div class="col s12 l8">
                <select th:field="*{category.id}" class="cs-select cs-skin-border">
                    <option value="" disabled="disabled">Select a category</option>
                    <option th:each="cat: ${categories}" th:value="${cat.id}" th:text="${cat.name}" th:style="|color:${cat.colorCode}|">Technology</option>
                </select>
            </div>
        </div>
        <div class="row">
            <div class="col s12">
                <button type="submit" class="button">Upload</button>
                <a href="javascript:window.location = document.referrer;" class="button">Cancel</a>
            </div>
        </div>
    </form>
Alexander Nikiforov
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Alexander Nikiforov
Java Web Development Techdegree Graduate 22,161 Points

Hi, Shadd. Post your project on GitHub. Otherwise it is hard to say. Its important to look at all project files.

I tried once again with Chris code - it works for me. You see the problem is that when you are trying to insert Gif into database, he is trying to convert Gif.dateUploaded to "Hexadecimal", which is strange. When Chris is uploading his Gif, his dateUploaded is being saved in table as VARBINARY(255). There is something wrong with your code. The missing class that is not here is Gif.java

Let me try to explain how it should work with saving Gif.dateUploaded. When you put object "gif" to Thymeleaf, using formNewGif method, you are creating new Gif() object. Right at that point, dateUploaded should be initialized, or may be later.

Anyway, when you get to addGif method, before saving Gif, try to print Gif's dateUploaded to see how it looks like. That is the place where I would start searching the bug.

But best would be to Share project on GitHub, so that I can reproduce error, and then write in Slack. It is easire to answer there.

2 Answers

For future students that may run into this issue:

The problem was with how the h2 database was taking in the dateUploaded information. To verify you have the same problem, check the H2 Console and see if under the GIF table, the DATEUPLOADED is of the datatype VARBINARY. To fix it, simply run the following SQL query in the h2 Console:

DELETE FROM GIF;
ALTER TABLE GIF ALTER COLUMN DATEUPLOADED DATETIME;

THIS WILL DELETE ANYTHING YOU MIGHT ALREADY HAVE IN THE GIF TABLE

vikas Rai
vikas Rai
9,703 Points

I was facing the same problem, thanks for help Shadd