Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Spring и EJB Module, TopLink, Glassfish, Netbeans 
V
    Опции темы
ShurikA
Дата 20.7.2009, 04:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Такое дело:

До сих пор все мои разработки сводились к Веб Сервисам либо апикациям на базе EJB и их клиентов. Так как всё это делалось под GlassFish, то создавался EJB Module который который общался с Persistence Layer и поддержывал всю нужную функциональность. По другую сторону реки создавалось веб приложение (которое в результате становилось на пример веб сервисом). Всё это собиралось в одну Enterprise Application.

В какой то момент мы решили воспользоваться спрингом со стороны клиента. Главным образом в связи с MVC и Spring Security. И вот тут, как говорится началось веселье.

Начьну с самого назойливого:

Приложение требует определённую сущность для пользователя.Достичь это можно при помощи имплементации класса UserDetailsService в котором, внутри метода loadUserByUsername собираем такого юзера какой на придёт в голову. и то что мне удалось достичь это создание этого пользователя с помощью прямого обращение к БД через DataSource. 
Но дело всё в том что у нас уже есть EJB Module который делает следующее:
Код

@Stateless
public class SysUserMgrBean implements SysUserMgrRemote {

    @PersistenceContext(unitName = "SecurityEjbPU")
    EntityManager em;

    public UserDetails loadUserByUsername(String username) {
        SystemUser su = null;
        try {
            su = (SystemUser) em.createNamedQuery("SystemUser.findByUsename").setParameter("username", username).getSingleResult();
        } catch (NoResultException nre) {
            Logger.getLogger(SysUserMgrBean.class.getName()).log(Level.INFO, "User not found by username!", nre);
            su = null;
        }
        return su;
    }
}

и SystemUser выгладит так:
Код

@Entity
@Table(name = "SystemUser")
@NamedQueries({
    @NamedQuery(name = "SystemUser.findByUsename", query = "SELECT c FROM SystemUser c WHERE username=:username")
})
public class SystemUser implements UserDetails, Serializable {

    private static final long serialVersionUID = 3571343430733369863L;
    /**
     * User auto ID
     */
    private Integer id;
    /**
     * Username
     */
    private String username;
    /**
     * User's password
     */
    private String password;
    /**
     * Users email
     */
    private String email;
    /**
     * Creation date
     */
    private Date creationDate;
    /**
     * Last update date
     */
    private Date updateDate;
    /**
     * Last operator ID
     */
    private Integer operator;
    /**
     * User roles
     */
    private Set<Authority> roles;

    /////////////////////
    //getters and setters
    /////////////////////
    @Id
    @Column(name = "id", nullable = false, unique = true, updatable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getId() {
        return id;
    }

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

    @Column(name = "username", nullable = false, insertable = true, unique = true, updatable = false, length = 30)
    @Basic(optional = false)
    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Column(name = "password", nullable = false, insertable = true, updatable = true, length = 45)
    @Basic(optional = false)
    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Column(name = "email", nullable = false, insertable = true, updatable = true, length = 30)
    @Basic(optional = false)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Basic(optional = false)
    @Column(name = "creationDate", nullable = false, insertable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    @Basic(optional = true)
    @Column(name = "updateDate", nullable = true, insertable = true, updatable = true)
    @Temporal(TemporalType.TIMESTAMP)
    public Date getUpdateDate() {
        return updateDate;
    }

    public void setUpdateDate(Date updateDate) {
        this.updateDate = updateDate;
    }

    @Column(name = "operator", nullable = true, updatable = true, insertable = true)
    @Basic(optional = true)
    public Integer getOperator() {
        return operator;
    }

    public void setOperator(Integer operator) {
        this.operator = operator;
    }

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "userId", cascade = CascadeType.ALL)
    public Set<Authority> getRoles() {
        return roles;
    }

    public void setRoles(Set<Authority> roles) {
        this.roles = roles;
    }

    public GrantedAuthority[] getAuthorities() {
        List list = new ArrayList();
        for (Authority role : roles) {
            list.add(new GrantedAuthorityImpl(role.getRole()));
        }
        return (GrantedAuthority[]) list.toArray(new GrantedAuthority[0]);

    }

    public boolean isAccountNonExpired() {
        return true;
    }

    public boolean isAccountNonLocked() {
        return true;
    }

    public boolean isCredentialsNonExpired() {
        return true;
    }

    public boolean isEnabled() {
        return true;
    }
}

 но мне так и не удалось обраться к SysUserMgrBean из loadUserByUsername, и чем дальше я двигаюсь тем больше путаюсь.
Может быть я вообще иду не в том направлении...
 smile  smile 


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 20.7.2009, 07:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



SysUserMgrBean - это класс (бин).
loadUserByUsername - это метод класса SysUserMgrBean.

Тогда что значит:
 
Цитата(ShurikA @  20.7.2009,  05:22 Найти цитируемый пост)
мне так и не удалось обраться к SysUserMgrBean из loadUserByUsername


Тебе не удается обратиться из метода к классу в котором он объявлен? Это как понять? smile 



--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ShurikA
Дата 20.7.2009, 08:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



powerOn, 
Мда, запутанно, но всё таки правильноsmile

Вот допустим самопальный UserDetailsService:
Код

public class SystemUserDetailsService implements UserDetailsService {
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        //вот тут я хочу обратиться к SysUserMgrBean и получить SystemUser
    }
}


просто у бина метод тоже называется loadUserByUsername...

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

вот ejb:
Код

@Stateless(mappedName="ejb/testBean")
public class NewSessionBean implements NewSessionRemote {

    public void businessMethod() {
        System.out.println("TEST TEST TEST");
    }
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method" or "Web Service > Add Operation")
}


в отдельном проекте (EJB Module).

едиственный способ которым мне удалось достучаться до бина это через lookup кодом:
Код

@Controller("accountController")
@Scope("session")
public class MyAccountController {
    //@EJB

    NewSessionRemote test;

    @RequestMapping(value = "/account.my")
    protected ModelAndView showAccountPage(HttpServletRequest request, HttpServletResponse responce) throws Exception {
        ModelAndView mv = new ModelAndView("account");
        ...
        InitialContext context = new InitialContext();
        test = (NewSessionRemote) PortableRemoteObject.narrow(
                context.lookup("ejb/testBean"),
                NewSessionRemote.class);
        test.businessMethod();
        return mv;
    }
}


Но никаким другим способом,
ну так:
Код

@Controller("accountController")
@Scope("session")
public class MyAccountController {
    @EJB
    NewSessionRemote test;

    @RequestMapping(value = "/account.my")
    protected ModelAndView showAccountPage(HttpServletRequest request, HttpServletResponse responce) throws Exception {
        ModelAndView mv = new ModelAndView("account");
        ...
        test.businessMethod();
        return mv;
    }
}


ни через конфигурацию:
Код

<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
   
    <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
    </bean>
    <bean id="viewResolver" class="web.view.LayoutVelocityViewResolver">
        <property name="cache" value="true"/>
        <property name="prefix" value=""/>
        <property name="suffix" value=".vm"/>
        <property name="layout" value="main.vm"/>
    </bean>
    <jee:remote-slsb id="testBean" jndi-name="ejb/testBean" business-interface="test.NewSessionRemote"/>
    
    <bean name="accountController" class="web.user.account.MyAccountController">
       <property name="test" ref="testBean"/>
    </bean>
</beans>


не работает...   smile 

Кроме того, когда я пытаюсь задеплоить оба модуля как одно приложение (Enterprise Application) не удаётся найти EJB даже через код. И единственный способ, это отдельно деплоить сначало EJB Module а потом Web Application.   smile 


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 20.7.2009, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



Цитата(ShurikA @  20.7.2009,  09:13 Найти цитируемый пост)
И единственный способ, это отдельно деплоить сначало EJB Module а потом Web Application.


ЕМНИП, то в application.xml можно указать чтобы деплой модулей проходил в порядке их объявления.

Я так понимаю что задача сводится к доступу к EJB из спринга? Если так, то об этом почитать можно тут.





--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ShurikA
Дата 20.7.2009, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Цитата(powerOn @  20.7.2009,  08:41 Найти цитируемый пост)
Я так понимаю что задача сводится к доступу к EJB из спринга? Если так, то об этом почитать можно тут.

хе хе, читал и перечитывал... не помогло.

На пример, как я уже и сказал выше, если попробовать делать injection так:
Код

<jee:remote-slsb id="testBean" jndi-name="ejb/testBean" business-interface="test.NewSessionRemote"/>
    
    <bean name="accountController" class="web.user.account.MyAccountController">
       <property name="test" ref="testBean"/>
    </bean>


то ошибка такая:
Код

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 50 in XML document from ServletContext resource [/WEB-INF/springapp-servlet.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'jee:remote-slsb'.


и соответственно:

Цитата(ShurikA @  20.7.2009,  07:13 Найти цитируемый пост)
2:
@Controller("accountController")
@Scope("session")
public class MyAccountController {
    @EJB
    NewSessionRemote test;
    @RequestMapping(value = "/account.my")
    protected ModelAndView showAccountPage(HttpServletRequest request, HttpServletResponse responce) throws Exception {
        ModelAndView mv = new ModelAndView("account");
        ...
        test.businessMethod();
        return mv;
    }
}


так тоже не работает.

Добавлено через 3 минуты и 19 секунд
Но допустим, с контроллером я решу в какой то момент, благо в документации спринга описанно, то есть работать должно.
Но каким образом мне получить бин внутри SystemUserDetailsService?


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
MisterCleric
Дата 20.7.2009, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Цитата

Но каким образом мне получить бин внутри SystemUserDetailsService? 


Через DependencyInjection:
Код

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
          p:systemPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE">
    </bean>

    <bean id="jndiEnvironment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="java.naming.factory.initial">${NAMING_FACTORY_INITIAL}</prop>
                <prop key="java.naming.provider.url">${provider.url}</prop>
            </props>
        </property>
    </bean>

    <bean id="ejbService" class="org.springframework.jndi.JndiObjectFactoryBean"
          p:jndiName="ear/EJBBean/remote"
          p:proxyInterface="EJBBeanInterface"
          p:jndiEnvironment-ref="jndiEnvironment"/>

<bean id="userDetailsService" class="your.package.SystemUserDetailsService"> ///Обязательно должен называться бин именно так: для spring-security надо
     <property name="userRemoteService" ref="ejbService"/>
</bean>



в общем это быстрый пример из моего проекта. Ну собственно, если почитать referance, который идет из дистрибутивом самого спринга и spring-security, то все более-менее становится понятно.
Я уже давно работаю в связке: RemoteEJB - WebSpring

Добавлено через 2 минуты и 43 секунды
Цитата

<jee:remote-slsb id="testBean" jndi-name="ejb/testBean" business-interface="test.NewSessionRemote"/>


Вот этот не заработал, там какие-то методы надо еще к бинам добавлять. Да и в доке посоветовали юзать простой JndiLookUp, т.е. тот бин пример, что я показал


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
ShurikA
Дата 20.7.2009, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



MisterCleric, 
Спасибо, а вопрос такой:
есть ли какая то разница если делать lookup кодом или DependencyInjection? Меня главное интересует скорость отработки...


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
MisterCleric
Дата 20.7.2009, 23:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



По-моему у JndiObjectFactoryBean есть какое-то кеширование инстансов, которые он производит. Нету под рукой исходников


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
ShurikA
Дата 21.7.2009, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



MisterCleric, 
Так как я совсем не привыкший к этим XML-ам, ты не мог бы пояснить что точьно делает каждая часть.
Главным образом вот эти две:
Код

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
          p:systemPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE">
    </bean>
    <bean id="jndiEnvironment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="java.naming.factory.initial">${NAMING_FACTORY_INITIAL}</prop>
                <prop key="java.naming.provider.url">${provider.url}</prop>
            </props>
        </property>
    </bean>


заранее спасибо.


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
MisterCleric
Дата 21.7.2009, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Привет. Попробую растолковать.
Первый - PropertyPlaceholderConfigurer - предназначен для того, что бы читать проперти и их значения из properties-файлов и вставлять в то место, где мы просим эти проперти специальной конструкцией, что мы и видим в следующем примере:
Цитата

${provider.url}

Так же у него есть возможность читать проперети из 
Код

System.getProperties();

что я и использую в моем примере.
Второй - PropertiesFactoryBean - просто создает объект типа Properties с тем набором, который мы ему перечисляем. В моем примере это будет набор пропертей для InitialContext, которые я потом инджектчу в бин для lookup по JNDI


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
ShurikA
Дата 8.8.2009, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



продолжение:

Вычитал много всего, в том чесле и то что EJB3 нужно инджектать так:
Код

<jee:jndi-lookup id="organizationEJB"
        jndi-name="java:comp/env/OrganizationConfigBean"
        expected-type="org.ejb.OrganizationConfigRemote">
    </jee:jndi-lookup>
        
    <bean id="organizationConfigController" class="web.org.config.OrganizationConfig">
        <property name="orgConfEjb" ref="organizationEJB"/>


при этом контроллер выглядит следующим образом:
Код

@Controller(value="organizationConfigController")
public class OrganizationConfig {

    private OrganizationConfigRemote orgConfEjb;

    @RequestMapping(value="/orgTypes.list", method=RequestMethod.GET)
    public ModelAndView showOrganizationTypesList(){
        ModelAndView vm = new ModelAndView("organizationTypesList");
        Set<OrganizationType> orgTypes = this.orgConfEjb.getAllOrganizationTypes();
        //create model for the view
        ArrayList otList = new ArrayList();
        for (OrganizationType ot : orgTypes){
            otList.add(ot.toMap());
        }
        vm.addObject("otList", otList);
        //cleanup
        otList = null;
        orgTypes = null;
        return vm;
    }

    public void setOrgConfEjb(OrganizationConfigRemote orgConfEjb) {
        this.orgConfEjb = orgConfEjb;
        System.out.println("EJB: "+this.orgConfEjb.getClass().getName());
    }
}


Во время деплоя в setOrgConfEjb метод передаётся переменная типа: 
org.ejb._OrganizationConfigRemote_Wrapper

Правильно ни это?

если да, то по идее после этого, в this.orgConfEjb я должен иметь свой бин.
но не тут то было, по какойто причине, когда я пытаюсь воспользоваться им в showOrganizationTypesList то он равен NULL. и естественно я вылетаю по NullPointerException.

Что я попускаю?


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
acvilon
  Дата 8.8.2009, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 16.4.2007
Где: Spb

Репутация: нет
Всего: нет



Привет, я разбирался с подобным, и выложил конечные исходники.
http://forum.vingrad.ru/forum/topic-268674...-springmvc.html
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0648 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.