Правильный способ сохранить новый объект во время выполнения в Java EE? - PullRequest
0 голосов
/ 29 мая 2018

Intro (Пропустите, если вам скучно;)

Привет, ребята, я работаю над школьным проектом, который я "унаследовал" от группы предыдущего года.Это веб-приложение, встроенное в Java EE, предназначенное для геймификации обучения пентестингу.Моя задача состояла в том, чтобы включить в приложение новую уязвимость (XXE). Существующее приложение смешивает аннотации CDI и EJB, хотя я пока не понимаю причину этого.

Ни я, ни кто-либо из моей группы не имеютлюбой опыт работы с Java EE, и хотя я приложил все усилия, чтобы набрать скорость в последние несколько недель, я немного растерялся из-за следующей проблемы, конкретно решая ее без «грязного взлома», который сломал бы шаблон MVC.

Проблема

Я могу успешно десериализовать загруженный пользователем файл .xml в экземпляр «Продукта» (или разрешить запуск эксплойта, когда пользователь загружает вредоносные данные,как я хочу).

Но сохранение объекта не работает, что, похоже, связано с областью действия моего класса UploadController.Пока что сохранение выполняется только в InitBean, который является одноэлементным и создается при запуске приложения.

Первоначальный замысел автора не позволял добавлять дополнительные объекты в базу данных после запускаapplication.

До сих пор я пробовал два маршрута: - Подражая использованию PersistenceContext из InitBean в моем UploadController (см. код ниже).Это приводит к исключению javax.persistence.TransactionRequiredException.Я прочитал об ошибке, думаю, у моего контроллера неправильный жизненный цикл, но я не совсем понял.

Я также попытался обернуть сохраняющуюся функциональность в InitBean и выставить ее как статический метод (чувствовал себя супернекрасиво, тоже не сработало).

Вопрос

Итак, в конечном итоге, мой вопрос: каков правильный подход для добавления элемента в базу данных после подачи заявкиначалось?Должен ли я сделать это из моего класса контроллера, если так, то как мне получить правильную область действия / транзакцию?Или я должен идти по другому пути полностью?Объяснения приветствуются.

Модель:

@Entity
@XmlRootElement
@Table(name = "product")
public class Product implements Serializable, Comparable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String name;

    @Column(nullable = false)
    private float price;

    @Column(length = 512) // hibernate default of 255 not sufficient for our flags
    private String description;

    @Column(name = "img_path")
    private String imagePath;

    @ManyToOne
    @JoinColumn(name = "category_fk")
    private Category category;

    @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Recension> recensions;

    @Column
    private boolean active;


    public Product() { 
    }

    public Product(String name, float price, String description, String imgPath, Category category) {
        this.name = name;
        this.price = price;
        this.description = description;
        this.imagePath = imgPath;
        this.category = category;
        this.active = true;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getImagePath() {
        return imagePath;
    }

    public void setImagePath(String imagePath) {
        this.imagePath = imagePath;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public Set<Recension> getRecensions() {
        return recensions;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }


    @Override
    public int compareTo(Object o) {
        return Long.compare(((Product) o).getId(), this.id);
    }    


    // Convenience methods

    public int ratingCount() {
        return recensions.size();
    }

    public float averageRating() {
        // avoid division by 0
        if (ratingCount() == 0) {
            return 0;
        }
        int sum = 0;
        for (Recension r : recensions) {
            sum += r.getRating();
        }
        return sum/ratingCount();

    }


}

ModelDAO:

package at.technikum.mic16.prj.dao;

import at.technikum.mic16.prj.entity.Category;
import at.technikum.mic16.prj.entity.Product;

import java.io.Serializable;
import java.util.List;
import javax.enterprise.inject.Model;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.lang3.StringEscapeUtils;

/**
 *
 * @author leandros
 */
@Model
public class ProductDAO implements Serializable {

    @PersistenceContext(unitName = "daisy-persunit")
    private EntityManager em;

    public Product findByID(Long id) {
        return em.find(Product.class, id);
    }

    /**
     * Find all products, optionally paginated
     * @param offset Offset to result set
     * @param count Number of rows to return, a value <= 0 will result in pagination being disabled
     * @return 
     */
    public List<Product> findAll(int offset, int count) {
        Query q = em.createQuery("FROM Product p WHERE active is true", Product.class);
        if (count > 0) {
            q.setFirstResult(offset);
            q.setMaxResults(count);
        }
        return q.getResultList();
    }

     /**
     * Find all products matching substring in name or description
     * @param substring Substring to match
     * @param offset Offset to result set
     * @param count Number of rows to return, a value <= 0 will result in pagination being disabled
     * @return 
     */
    public List<Product> findByNameOrDescription(String substring, int offset, int count) {
        Query q = em.createQuery("FROM Product p WHERE (name like :substring or description like :substring) AND active is true", Product.class);
        q.setParameter("substring", "%" + substring + "%");
        if (count > 0) {
            q.setFirstResult(offset);
            q.setMaxResults(count);
        }

        return q.getResultList();
    }

    /**
     * Find all products - this is vulnerable to SQL injection and also unescapes input by purpose
     * Result is also sorted independently of SQL (no order by) in order to display record with reward first (highest id, see comparator)
     * @param queryString
     * @return 
     */
    public List<Product> findByExactName(String queryString) {
        String unescaped = StringEscapeUtils.unescapeHtml4(queryString);
        Query q = em.createQuery("FROM Product p WHERE active is true AND name = '" + unescaped + "'", Product.class);
        List result = q.getResultList();
        result.sort(null);
        return result;
    }

     /**
     * Find all products matching specific category
     * @param category Category to match
     * @param offset Offset to result set
     * @param count Number of rows to return, a value <= 0 will result in pagination being disabled
     * @return 
     */
    public List<Product> findByCategory(Category category, int offset, int count) {
        Query q = em.createQuery("FROM Product p WHERE category_fk = :category AND active is true", Product.class);
        q.setParameter("category", category);
        if (count > 0) {
            q.setFirstResult(offset);
            q.setMaxResults(count);
        }
        return q.getResultList();
    }

    /**
     * Find inactive products
     * @return List of inactive products
     */
    public List<Product> findInactive() {
        Query q = em.createQuery("FROM Product p WHERE active is false", Product.class);
        return q.getResultList();
    }

    public void persist(Product...products) {
        for (Product product : products) {
            em.persist(product);
        }
    }

    public void merge(Product product) {
        em.merge(product);
    }

    public void delete(Product product) throws EntityNotFoundException {
        // attach and delete it...
        Product attached = em.find(Product.class, product.getId());
        if (attached != null) {
            em.remove(attached);
        } else {
            throw new EntityNotFoundException("Product not found with id: " + product.getId());
        }
    }



}

InitBean

@Singleton
@LocalBean
@Startup
public class InitBean {

    // file path of JS to by executed by phantom JS
    private static final String XSS_FILE_PATH = "/home/daisy/.config";
    // this file is intended for holding a token receivable by exploiting the command execution in admin interface
    public static final String HIDDEN_FILE_PATH_CE = "/tmp/TOKEN_REWARD.TXT";
    // this file is intended for holding a token receivable by exploiting the xxe vulnerability in the upload section
    public static final String HIDDEN_FILE_PATH_XXE = "/tmp/hidden/TOKEN_REWARD2.TXT";
    // this user bears a special description -> reward token
    private static final String USER_WITH_TOKEN = "user2@foo.at";
    //Admin User Testing
    private static final String ADMIN_USER = "admin@foo.at";

    @Inject
    private WebshopService webshopService;

    @Inject
    private CategoryDAO categoryDAO;
    @Inject
    private ProductDAO productDAO;
    @Inject
    private OrderItemDAO orderItemDAO;
    @Inject
    private PlacedOrderDAO placedOrderDAO;
    @Inject
    private RecensionDAO recensionDAO;
    @Inject
    private UserDAO userDAO;
    @Inject
    private UserRoleDAO userRoleDAO;

    private String installationToken;
    private Map<Vulnerability, String> rewardTokens;


    public void setInstallationToken(String installationToken) {
        this.installationToken = installationToken;
    }

    public Map<Vulnerability, String> getRewardTokens() {
        return rewardTokens;
    }

    public void setRewardTokens(Map<Vulnerability, String> rewardTokens) {
        this.rewardTokens = rewardTokens;
    }



    @PostConstruct
    public void init() {

        try {
            insertSampleData();
            installationToken = webshopService.retrieveInstallationToken();
            /* if there is no token, retrieving it would fail with FileNotFoundException
            so just go on inserting vulnerability data...
             */
            generateRewardTokens();
            insertVulnerabilityData();
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
            Logger.getLogger(InitBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException ignore) {
            // retrieving installation token failed
        } catch (IOException ex) {
            Logger.getLogger(InitBean.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Inserts sample data into the database
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException 
     */
    private void insertSampleData() throws NoSuchAlgorithmException, UnsupportedEncodingException {

        UserRole user1Role = new UserRole("han", UserRole.Role.CUSTOMER);
        UserRole user2Role = new UserRole(USER_WITH_TOKEN, UserRole.Role.CUSTOMER);
        UserRole user3Role = new UserRole(ADMIN_USER, UserRole.Role.ADMIN);
        userRoleDAO.persist(user1Role, user2Role, user3Role);

        User user1 = new User("user1@foo.at", JBossPasswordUtil.getPasswordHash("user1"), "User", "1");
        User user2 = new User(USER_WITH_TOKEN, JBossPasswordUtil.getPasswordHash(RandomStringUtils.randomAlphanumeric(12)), "User", "2");
        User user3 = new User(ADMIN_USER, JBossPasswordUtil.getPasswordHash("admin"), "Iam", "God");
        userDAO.persist(user1, user2, user3);

        Category clothes = new Category("Clothes");
        categoryDAO.persist(clothes);

        Category men = new Category("Men");
        men.setParent(clothes);
        categoryDAO.persist(men);

        Category trousersMen = new Category("Trousers");
        trousersMen.setParent(men);
        categoryDAO.persist(trousersMen);

        Category electro = new Category("Electro");
        categoryDAO.persist(electro);

        Category telly = new Category("Television");
        telly.setParent(electro);
        categoryDAO.persist(telly);

        Category hoover = new Category("Hoover");
        hoover.setParent(electro);
        categoryDAO.persist(hoover);

        Category smartphone = new Category("Smartphone");
        smartphone.setParent(electro);
        categoryDAO.persist(smartphone);

        Product phillips1 = new Product("Philips 55PUK4900", 679.99f, "This new Phillips is superb...", "images/products/Phillips_55PUK4900.jpg", telly);
        Product phillips2 = new Product("Phillips 55PUS6031", 998.99f, "The brand new Phillips...", "images/products/Phillips_55PUS6031.jpg", telly);
        Product phillips3 = new Product("Phillips 50PFK4109", 328.99f, "This new Phillips is not as good...", "images/products/Phillips_50PFK4109.jpg", telly);
        Product samsung1 = new Product("Samsung UE55JU6470", 850.00f, "This new Samsung is superb...", "images/products/Samsung_UE55JU6470.jpg", telly);
        Product samsung2 = new Product("Samsung UE55K5660", 1100.00f, "This new Samsung is not as good...", "images/products/Samsung_UE55K5650.jpg", telly);
        Product samsung3 = new Product("Samsung UE65JU6070", 1200.99f, "This new Samsung is not as good...", "images/products/Samsung_UE65JU6070.jpg", telly);
        Product panasonic1 = new Product("Panasonic TX-49DXW654", 679.99f, "This new Phillips is superb...", "images/products/Panasonic_TX49DXW654.jpg", telly);
        Product panasonic2 = new Product("Panasonic TX65AXW904", 998.99f, "This new Phillips is not as good...", "images/products/Panasonic_TX65AXW904.jpg", telly);
        Product panasonic3 = new Product("Panasonic TX55CXW684", 328.99f, "This new Phillips is not as good...", "images/products/Panasonic_TX55CXW684.jpg", telly);
        Product hoover1 = new Product("iRobot Roomba 980", 750.90f, "Brand new and strong...", "images/products/Irobot_Roomba980.jpg", hoover);
        Product hoover2 = new Product("iRobot Roomba 886", 930.90f, "Brand new and strong...", "images/products/Irobot_Roomba886.jpg", hoover);
        Product hoover3 = new Product("iRobot Roomba 875", 487.90f, "Brand new and strong...", "images/products/IrobotRoomba875.jpg", hoover);
        Product hoover4 = new Product("Dyson Big Ball Parquet", 640.90f, "Brand new and strong...", "images/products/Dyson_Bigball1.jpg", hoover);
        Product hoover5 = new Product("Dyson DC37c Parquet", 321.90f, "Brand new and strong...", "images/products/Dyson_Dc37.jpg", hoover);
        Product hoover6 = new Product("Dyson DC37 Musclehead", 219.90f, "Brand new and strong...", "images/products/Dyson_Dc37misclehead.jpg", hoover);
        Product smartphone1 = new Product("Apple Iphone 7", 860.90f, "Brand new and strong...", "images/products/Iphone7.jpg", smartphone);
        Product smartphone2 = new Product("Apple Iphone SE", 450.90f, "Brand new and strong...", "images/products/Iphone_SE.jpg", smartphone);
        Product smartphone3 = new Product("Samsung Galaxy S8", 750.90f, "Brand new and strong...", "images/products/Samsung_S8.jpg", smartphone);
        Product smartphone4 = new Product("Samsung Galaxy S6", 650.90f, "Brand new and strong...", "images/products/Samsung_S6.jpg", smartphone);
        Product smartphone5 = new Product("Google Pixel", 800.90f, "Brand new and strong...", "images/products/Google_Pixel.jpg", smartphone);
        Product smartphone6 = new Product("Huawei P10", 700.90f, "Brand new and strong...", "images/products/Huawei_P10.jpg", smartphone);
        Product jeans1 = new Product("Lewis", 110.90f, "Brand new and strong...", "images/products/jeans1.jpg", trousersMen);
        Product jeans2 = new Product("G-Star P10", 120.90f, "Brand new and strong...", "images/products/jeans2.jpg", trousersMen);
        Product jeans3 = new Product("Review P10", 60.90f, "Brand new and strong...", "images/products/jeans3.jpg", trousersMen);
        Product jeans4 = new Product("Replay", 75.90f, "Brand new and strong...", "images/products/jeans4.jpg", trousersMen);
        Product jeans5 = new Product("Diesel", 160.90f, "Brand new and strong...", "images/products/jeans5.jpg", trousersMen);
        Product jeans6 = new Product("Mustang", 55.90f, "Brand new and strong...", "images/products/jeans6.jpg", trousersMen);

        productDAO.persist(phillips1, phillips2, phillips3, samsung1, samsung2, samsung3, panasonic1, panasonic2, panasonic3, hoover1, hoover2, hoover3, hoover4, hoover5, hoover6,
                smartphone1, smartphone2, smartphone3, smartphone4, smartphone5, smartphone6, jeans1, jeans2, jeans3, jeans4, jeans5, jeans6);

        Recension recension1 = new Recension();
        recension1.setCreationDate(LocalDateTime.now().minusDays(14));
        recension1.setProduct(phillips1);
        recension1.setRating(4);
        recension1.setUser(user1);
        recension1.setText("I like it");

        Recension recension2 = new Recension();
        recension2.setCreationDate(LocalDateTime.now().minusDays(3).minusSeconds((int) (Math.random()*1337)));
        recension2.setProduct(phillips1);
        recension2.setRating(3);
        recension2.setUser(user2);
        recension2.setText("It's ok, don't expect too much.");

        recensionDAO.persist(recension1, recension2);

    }

    /**
     * Generates all the reward tokens in rewardTokens
     */
    private void generateRewardTokens() {
        rewardTokens = new HashMap<>();
        for (Vulnerability v : Vulnerability.values()) {
            try {
                rewardTokens.put(v, DaisyPointsCrypter.encryptMessage(installationToken, "Vulnerability|" + v.name()));
                //Logger.getLogger(InitBean.class.getName()).log(Level.INFO, "Generated token: ".concat(rewardTokens.get(v)));
            } catch (DaisyPointsEncryptionException ex) {
                rewardTokens = null;
                Logger.getLogger(InitBean.class.getName()).log(Level.SEVERE, "Error generating reward tokens", ex);
            }

        }
    }

    /**
     * Puts reward tokens to their respective places
     * @throws IOException 
     */
    public void insertVulnerabilityData() throws IOException {

        /*
        this should only happen upon invocation via TokenController and not
        on subsequent restarts, when token is already known
        */
        if (rewardTokens == null) {
            generateRewardTokens();
        }

        // hidden product - find via SQL injection
        Category hoover = categoryDAO.findByName("Hoover");
        Product prod1 = new Product("SQL Injection exploited!", 666, "Congratulations, here is your token for the points system:\n".concat(rewardTokens.get(Vulnerability.SQLI_PRODUCTS)), "images/thumbs_up.png", hoover);
        prod1.setActive(false);
        productDAO.persist(prod1);

        // hidden user - find via indirect object reference
        User user2 = userDAO.findById(USER_WITH_TOKEN);
        user2.setDescription(rewardTokens.get(Vulnerability.INSECURE_DIRECT_OBJECT_REFERENCE));

        // hidden file - find via hidden directory and CommandService
        File f = new File(HIDDEN_FILE_PATH_CE);
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(f));
            bw.write("Command execution exploited, here is your token for the points system:");
            bw.newLine();
            bw.write(rewardTokens.get(Vulnerability.HIDDEN_FILE));
            bw.newLine();
            bw.flush();
        } finally {
            FileUtil.safeClose(bw);
        }

        // hidden file - find via hidden directory and CommandService
        writeFile(HIDDEN_FILE_PATH_CE, Vulnerability.HIDDEN_FILE);

        // hidden file - find via hidden directory and CommandService
        writeFile(HIDDEN_FILE_PATH_XXE, Vulnerability.XXE_UPLOAD);


        // prepare phantom JS script
        f = new File(XSS_FILE_PATH);
        bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(f));
            bw.write(preparePhantomJSScript());
            bw.flush();
        } finally {
            FileUtil.safeClose(bw);
        }

    }

    private void writeFile(String pathname, Vulnerability vulnerability) throws IOException {
        File f;
        BufferedWriter bw;
        f = new File(pathname);
        bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(f));
            bw.write("Command execution exploited, here is your token for the points system:");
            bw.newLine();
            bw.write(rewardTokens.get(vulnerability));
            bw.newLine();
            bw.flush();
        } finally {
            FileUtil.safeClose(bw);
        }
    }

    /**
     * Delete any structures (DB reows, files) containing reward tokens
     */
    public void deleteVulnerabilityData() {
        for (Product p : productDAO.findInactive()) {
            productDAO.delete(p);
        }

        User user2 = userDAO.findById(USER_WITH_TOKEN);
        user2.setDescription("");

        File f = new File(HIDDEN_FILE_PATH_CE);
        f.delete();

        f = new File(XSS_FILE_PATH);
        f.delete();

    }

    /**
     Writes token in script invoked by phantom JS
     * @param token
     * @return
     * @throws UnsupportedEncodingException
     * @throws DaisyPointsEncryptionException 
     */
    private String preparePhantomJSScript() throws UnsupportedEncodingException {
        // this holds the phantom JS script to be executed in portable fashion
        String base64 = "dmFyIHBhZ2UgPSByZXF1aXJlKCd3ZWJwYWdlJykuY3JlYXRlKCk7CgpwYWdlLnNldHRpbmdzLnVzZXJBZ2VudCA9ICdUT0tFTic7CnBhZ2Uudmlld3BvcnRTaXplID0geyB3aWR0aDogMTkyMCwgaGVpZ2h0OiAxMDgwIH07CgpwYWdlLm9wZW4oJ2h0dHA6Ly8xMjcuMC4wLjE6ODA4MC9kYWlzeS13ZWIvJywgZnVuY3Rpb24oKSB7CgogICAgICAgIHBhZ2UuZXZhbHVhdGUoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICBQcmltZUZhY2VzLmFiKHtzOmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1thbHQ9InByb2R1Y3QtMSJdJykuZ2V0QXR0cmlidXRlKCJpZCIpfSk7CiAgICAgICAgfSk7CgogICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICBwYWdlLmV2YWx1YXRlKGZ1bmN0aW9uKCkge30pOwogICAgICAgIH0sIDIwMDApOwoKICAgICAgICBjb25zb2xlLmxvZygiZmluaXNoIik7CgogICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAvL3BhZ2UucmVuZGVyKCd0ZXN0LnBuZycpOwogICAgICAgICAgICAgICAgcGhhbnRvbS5leGl0KCk7CiAgICAgICAgfSwgMjAwMCk7Cn0pOwo=";
        String script = new String(Base64.decodeBase64(base64), "UTF-8");

        // modify user agent to use appropriate reward token string
        return script.replace("TOKEN", rewardTokens.get(Vulnerability.XSS_REMOTE_SCRIPT));
    }

    //Awful Hack:
//    public void persistProduct(Product product){
//        productDAO.persist(product);
//    }

}

UploadController

package at.technikum.mic16.prj.controller;

/**
 * Created by Dave on 11/05/2018.
 */
@ManagedBean(name = "uploadController")
@ApplicationScoped
@Startup
@Singleton
//@Stateful
public class UploadController implements Serializable {
    private Part file;

    private String xmlString;

    @Inject
    private ProductDAO productDAO;

    public void doOutput(Product product) {

        if (product == null) return;

        JAXBContext jc;

        {
            try {

                PrintStream ps = new PrintStream(new StringOutputStream(), true);

//                PrintStream ps = new PrintStream(new File("product.xml"));
                System.setOut(ps);

                jc = JAXBContext.newInstance(Product.class);

                Marshaller marshaller = jc.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                marshaller.marshal(product, System.out);


            } catch (JAXBException e) {
                e.printStackTrace();
            }
        }
    }

    public void upload() {
        try {
            setXmlString(new Scanner(file.getInputStream())
                    .useDelimiter("\\A").next());

            Product product = deserializeProduct(getXmlString());

            productDAO.persist(product);

            doOutput(product);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Part getFile() {
        return file;
    }

    public void setFile(Part file) {
        this.file = file;
    }


    public String getXmlString() {
        return xmlString;
    }

    public void setXmlString(String pXmlString) {
        xmlString = pXmlString;
    }

    //Parsing xml back to object (+vuln) -> should eventally go into another class


    public Product deserializeProduct(String xmlString) {
        try {
            JAXBContext jc = JAXBContext.newInstance(Product.class);

            XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
            xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true);
            xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, true);
            XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(new StringReader(xmlString));

            Unmarshaller unmarshaller = jc.createUnmarshaller();
            return (Product) unmarshaller.unmarshal(xmlStreamReader);

        } catch (JAXBException pE) {
            pE.printStackTrace();
            return null;
        } catch (XMLStreamException pE) {
            pE.printStackTrace();
            return null;
        }
    }


}

Заранее спасибо за любую помощь!

1 Ответ

0 голосов
/ 29 мая 2018

Ранее я использовал @Singleton + @Startup как то, что вы делаете.
, но у этого метода есть некоторые проблемы.
Теперь я использую этот метод:

<persistence 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"
             version="2.1">
  <persistence-unit name="db-connection" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <jta-data-source>JTA-Connection</jta-data-source>
    <non-jta-data-source>None-JTA-Connection</non-jta-data-source>
    <properties>
        <property name="tomee.jpa.cdi" value="false"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>
        <!--<property name="hibernate.current_session_context_class" value="thread"/>-->
        <property name="hibernate.event.merge.entity_copy_observer" value="allow"/>
        <property name="hibernate.enable_lazy_load_no_trans" value="true"/>
        <!--<property name="hibernate.show_sql" value="true"/>-->
        <!--<property name="hibernate.format_sql" value="true"/>-->
        <!--<property name="hibernate.hbm2ddl.auto" value="create-drop"/>-->
        <!--<property name="hibernate.hbm2ddl.auto" value="create"/>-->
        <!--<property name="hibernate.hbm2ddl.auto" value="update"/>-->

        <property name="hibernate.hbm2ddl.import_files_sql_extractor"
                  value="org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor"/>
        <property name="hibernate.hbm2ddl.import_files" value="initialize-database.sql"/>
    </properties>
  </persistence-unit>
</persistence>

примечание: hibernate.hbm2ddl.import_files в persistence.xml.
на самом деле слишком удобно.

...