简体   繁体   English

在Java EE中在运行时持久保存新对象的正确方法?

[英]Right way to persist new object at runtime in Java EE?

Intro (Skip if you get bored ;) 简介 (如果感到无聊,请跳过;)

Hi guys, I'm working on a school project that I "inherited" from a previous year group. 嗨,大家好,我正在做一个我去年从“继承”下来的学校项目。 It's a Webapp built in Java EE meant for gamification of pentesting training. 这是一个用Java EE内置的Webapp,旨在对笔试训练进行游戏化。 My task was to include a new vulernability (XXE) in the application.The existing application mixes CDI and EJB annotations, although I've yet to understand the reason for that. 我的任务是在应用程序中包括一个新的漏洞(XXE)。现有的应用程序混合了CDI和EJB批注,尽管我尚未弄清原因。

Neither I nor anyone in my group has any experience with Java EE, and while I did my best to get up to speed in the last few weeks, I'm a little lost at the following problem, specifically solving it without a "dirty hack" that would break the MVC pattern. 我和我的小组中的任何人都没有Java EE的经验,尽管在过去的几周中我尽了最大的努力来加快速度,但我对以下问题有些迷失,特别是在没有“肮脏的骇客”的情况下解决了该问题。 ”将破坏MVC模式。

Problem 问题

I can successfully deserialize a user-uploaded .xml to an instance of "Product" (or let an exploit be triggered when the user uploads malicious data, just as I want). 我可以成功地将用户上传的.xml反序列化为“产品”的实例(或根据需要,在用户上传恶意数据时触发漏洞利用)。

But persisting the object doesn't work, which seems to have to do with the scope of my UploadController class. 但是持久化对象不起作用,这似乎与我的UploadController类的范围有关。 So far persistence is only done in the InitBean which is a singleton and is instantiated as soon as the app starts. 到目前为止,持久性仅在InitBean中完成,InitBean是一个单例,并在应用程序启动后立即实例化。

It was not the original author's intent to allow for further objects to be added to the database after starting the application. 启动该应用程序后,原始作者的意图不是允许将更多对象添加到数据库中。

I tried two routes so far: - Mimicking the usage of the PersistenceContext from InitBean in my UploadController (see code below). 到目前为止,我尝试了两种方法:-在我的UploadController中模仿InitBean中PersistenceContext的用法(请参见下面的代码)。 This results in javax.persistence.TransactionRequiredException. 这将导致javax.persistence.TransactionRequiredException。 I did some reading on the error, I guess my controller has the wrong lifecycle, but I don't quite get it. 我对错误进行了一些阅读,我猜我的控制器的生命周期错误,但是我不太明白。

I also tried wrapping the persisting functionality in InitBean and exposing it as static method (felt super ugly, also didn't work). 我还尝试将持久性功能包装在InitBean中,并将其作为静态方法公开(感觉非常丑陋,也行不通)。

Question

So, ultimately, my question: What is the right approach to add an item to the database after the application has started? 因此,最终,我的问题是:在应用程序启动后,向数据库添加项目的正确方法是什么? Should I even do it from my controller class, if so, then how do I get the right scope/Transaction? 如果是这样,我是否应该从我的控制器类中执行此操作,那么如何获得正确的作用域/事务? Or should I go down another path entirely? 还是我应该完全走另一条路? Explanations are much appreciated. 解释非常感谢。

Model: 模型:

@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: 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 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;
        }
    }


}

Thanks for any help in advance! 感谢您的任何帮助!

Previously I used @Singleton + @Startup like something you do that . 以前,我使用@Singleton + @Startup就像执行此操作一样。
but this method has some problems . 但是这种方法存在一些问题。
now I use this method : 现在我使用这种方法:

<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>

note : hibernate.hbm2ddl.import_files in persistence.xml . 注意:persistence.xml中的hibernate.hbm2ddl.import_files。
actually too more handy . 其实太方便了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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