Хобрук: Ваш путь к мастерству в программировании

JAVA EE EJB без сохранения состояния IllegalArgumentException: невозможно установить поле

У меня возникли проблемы при изучении ejb. Все, что я хочу, это написать простое приложение для работы с базой данных. Вот мой код:

Сервлет — Main.java

package main;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "Main", urlPatterns = {"/"})
public class Main extends HttpServlet {

@EJB
private NoteSB noteSB;

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    PrintWriter out = response.getWriter();
        List<Note> notes = noteSB.getNotes();
        for( int i=0,len=notes.size() ; i<len ; ++i ) {
            out.println(notes.get(i));
        }

}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
}


@Override
public String getServletInfo() {
    return "Short description";
}


}

Объект — Note.java

    /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package main;

import java.io.Serializable;
import java.security.Timestamp;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "NOTES")
public class Note implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String note;
    private Timestamp date;

    public Note(){}

    public Note(String note, Timestamp date) {
        this.note = note;
        this.date = date;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Note)) {
            return false;
        }
        Note other = (Note) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Note["+ this.date +"]: " + this.note;
    }

}

Бин сеанса без сохранения состояния — NoteSB.java

    package main;

import java.util.List;
import javax.annotation.PreDestroy;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
@LocalBean
public class NoteSB {


    @PersistenceContext(name = "jee-warPU")
    private EntityManager em;

    public void newNote(Note n) {
        em.persist(n);
    }

    public List<Note> getNotes() {
        return em.createNativeQuery("SELECT * FROM NOTES").getResultList();
    }

    @PreDestroy
    public void destroy() {
        em.close();
    }
}

persistance.xml

    <?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="jee-warPU" transaction-type="JTA">
    <jta-data-source>java:comp/DefaultDataSource</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="javax.persistence.schema-generation.database.action" value="create"/>
    </properties>
  </persistence-unit>
</persistence>

И вот моя трассировка стека:

    Info:   file:/C:/Users/BB/Documents/NetBeansProjects/jee/jee-war/build/web/WEB-INF/classes/_jee-warPU logout successful
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
Info:   file:/C:/Users/BB/Documents/NetBeansProjects/jee/jee-war/build/web/WEB-INF/classes/_jee-warPU login successful
Info:   Portable JNDI names for EJB NoteSB: [java:global/jee-war/NoteSB, java:global/jee-war/NoteSB!main.NoteSB]
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
Info:   Loading application [jee-war] at [/jee-war]
Info:   jee-war was successfully deployed in 783 milliseconds.
Info:   WebModule[null] ServletContext.log():Marking servlet Main as unavailable
Warning:   StandardWrapperValve[Main]: Allocate exception for servlet Main
java.lang.IllegalArgumentException: Can not set main.NoteSB field main.Main.noteSB to main.Main
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
    at java.lang.reflect.Field.set(Field.java:758)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:688)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:507)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:141)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:347)
    at com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:991)
    at com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:2130)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1404)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:1211)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:237)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
    at java.lang.Thread.run(Thread.java:745)

Буду признателен за любую помощь! Я пробовал много руководств и вариантов и до сих пор не могу понять, что это такое. Копание трассировки стека просто сводит меня с ума, я частично понимаю ошибки, но не знаю, что делать, пожалуйста, помогите :)


Ответы:


1

Вам не хватает видимых методов доступа для поля noteSB. Добавьте в класс Main следующие методы получения и установки:

public class Main extends HttpServlet {

    // all your current code here

    public NoteSB getNoteSB() {
        return this.noteSB;
    }

    public void setNoteSB(NoteSB noteSB) {
        this.noteSB = noteSB;
    }
}

См. спецификацию JavaBean. Конкретно этот отрывок:

7.1 Методы доступа

Доступ к свойствам всегда осуществляется через вызовы методов их объекта-владельца. Для читаемых свойств будет метод getter для чтения значения свойства. Для свойств с возможностью записи будет метод setter, позволяющий обновлять значение свойства. Таким образом, даже когда автор сценария вводит что-то вроде «b.Label = foo», в целевом объекте по-прежнему вызывается метод для установки свойства, и целевой объект имеет полный программный контроль.

Таким образом, свойства должны быть не просто полями данных, они могут быть вычисляемыми значениями. Обновления могут иметь различные программные побочные эффекты. Например, изменение свойства цвета фона компонента может также привести к тому, что компонент будет перекрашен новым цветом.

Для простых свойств сигнатуры типа доступа:

void setFoo(PropertyType value); // simple setter
PropertyType getFoo(); // simple getter
27.02.2015
  • Такое поведение мне незнакомо. Можете ли вы объяснить, почему для успешной инъекции стеклянным рыбкам нужны геттеры и сеттеры? Есть ли ссылка на спецификацию? 28.02.2015
  • Это могло бы работать без геттера и сеттера, если бы переменная была объявлена ​​как public NoteSB noteSB;, но это нарушило бы инкапсуляцию. 28.02.2015
  • Мы имеем дело с weblogic, jboss и widfly, и они не требуют публичного модификатора в объявлении поля с аннотацией @EJB (точка внедрения), мы используем private или protected - эти ограничения доступа не являются препятствием для внедрения. Я не могу найти доказательств в спецификации, описывающей этот момент. Ты знаешь? 01.03.2015
  • Какую спецификацию вы имеете в виду? Имейте в виду, что когда вы размещаете аннотацию @EJB в объявлении поля, поведение по умолчанию заключается в использовании методов getter и setter путем отражения. Если таких средств доступа нет, только тогда EJB будет смотреть непосредственно на объявление поля путем отражения. Это связано с тем, что спецификация Enterprise JavaBeans является расширением спецификации JavaBean, упомянутой в моем ответе. 01.03.2015
  • И что я должен сделать в случае с Glassfish, если я хочу скрыть аннотированное поле EJB для внутренних целей, скрыть от внешнего вида? В спецификации EJB не нашел никакой информации об ограничениях инъекций и модификаторов полей, буду читать внимательнее. На мой взгляд, поведение Glassfish, описанное в основном вопросе ветки, ошибочно. 02.03.2015
  • Все наоборот. JBoss и WebLogic ошибаются, если молчат о приватном поле без методов доступа в JavaBean. Если вы хотите скрыть поля, попробуйте уменьшить видимость методов доступа? 02.03.2015
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..