Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] Eclipselink 2 / JPA 2 integration with Spring on WebLogic 12.1.1

Michael,

                Hi, I will look into your spring configuration when I get back into the office later today.

                If you switch from EE container managed spec development to VMWare spring development – your configuration could change in several ways depending on whether you are running the spring DI container in your WAR or EJB container.

                From a quick look on my IPhone, the CNFE exception is due to the persistence unit and entity classes being in different classloaders.  The weaving exception I will need to look at.  Normally the EJB container proxy handles this without Spring.

 

 

                /Michael

 

 

From: Michael Gitelman [mailto:mgitelman@xxxxxxxxxxxxxxx]
Sent: February 17, 2012 12:37
To: Michael O'Brien
Subject: Eclipselink 2 / JPA 2 integration with Spring on WebLogic 12.1.1

 

Hi Michael,

 

Thank you for your help on trying to make JPA 2 / EclipseLink 2 to work on Weblogic 10.3.4. I have been able to persuade my superiors to move to WebLogic 12.1.1.

 

However, I am having a bit of a problem trying to deploy my persistence.xml. I have changed my design a bit. Now, instead of an EJB I am using a Spring configured DAO class (I am integrating my piece into a larger Spring-configured application). I use the same entities. I believe my problem is due to the Spring configuration.

 

That’s how my project looks like:

DAO Class

package dti.admin.cp.dao;

 

import dti.admin.cp.entity.ConfigEventHeader;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Transactional;

 

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

import javax.persistence.Query;

import java.util.List;

 

@Component   

public class ConfigEventHeaderDao {

    @PersistenceContext(unitName = "ConfigPropsPU")

    private EntityManager em;

 

    @Transactional

    public void persist(Object object) {

        em.persist(object);

    }

 

    /**

     * Returns a list of ConfigEventHeader objects in the database

     * @return List<ConfigEventHeader>

     */

    public List<ConfigEventHeader> retrieve() {

        Query query = em.createNamedQuery("ConfigEventHeader.findAll");

          System.out.println(new java.sql.Timestamp(System.currentTimeMillis()) + " -- "

                +this.getClass().getName()+ " -- "+"Retrieving a List ConfigEventHeaders...");

        return query.getResultList();

    }

 

        /**

     * Update the ConfigEventHeader record

     * @param configEventHeader object to be updated

     * @return Customer

     */

    @Transactional

    public ConfigEventHeader update(ConfigEventHeader configEventHeader) {

         System.out.println(new java.sql.Timestamp(System.currentTimeMillis()) + " -- "

                +this.getClass().getName()+ " -- "+"ConfigEventHeader Update: "+configEventHeader.getConfigEventHeaderPk());

        return em.merge(configEventHeader);

    }

 

 

    public ConfigEventHeader findByEntityPk(ConfigEventHeader configEventHeader) {

        Query query = em.createNamedQuery("ConfigEventHeader.findByConfigEventHeaderPk");

          System.out.println(new java.sql.Timestamp(System.currentTimeMillis()) + " -- "

                +this.getClass().getName()+ " -- "+"findByEntityPk ConfigEventHeader: "+configEventHeader.getConfigEventHeaderPk());

        return (ConfigEventHeader)query.getSingleResult();

    }

 

    public ConfigEventHeader loadById(Long id) {

          System.out.println(new java.sql.Timestamp(System.currentTimeMillis()) + " -- "

                +this.getClass().getName()+ " -- "+"Loading ConfigEventHeader by Id: "+id);

                return em.find(ConfigEventHeader.class, id);

    }

 

    @Transactional

    public void delete(ConfigEventHeader configEventHeader){

           System.out.println(new java.sql.Timestamp(System.currentTimeMillis()) + " -- "

                +this.getClass().getName()+ " -- "+"Deleting ConfigEventHeader: "+configEventHeader.getConfigEventHeaderPk());

        em.remove(em.merge(configEventHeader));

    }

}

 

A sample entity class

package dti.admin.cp.entity;

 

import java.io.Serializable;

import java.util.Date;

import java.util.List;

import javax.persistence.Basic;

import javax.persistence.CascadeType;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.NamedQueries;

import javax.persistence.NamedQuery;

import javax.persistence.OneToMany;

import javax.persistence.Table;

import javax.persistence.Temporal;

import javax.persistence.TemporalType;

 

@Entity

@Table(name = "CONFIG_EVENT_HEADER")

@NamedQueries({

    @NamedQuery(name = "ConfigEventHeader.findAll", query = "SELECT c FROM ConfigEventHeader c"),

    @NamedQuery(name = "ConfigEventHeader.findByConfigEventHeaderPk", query = "SELECT c FROM ConfigEventHeader c WHERE c.configEventHeaderPk = :configEventHeaderPk"),

    @NamedQuery(name = "ConfigEventHeader.findByBuildId", query = "SELECT c FROM ConfigEventHeader c WHERE c.buildId = :buildId"),

    @NamedQuery(name = "ConfigEventHeader.findByEventStatusCode", query = "SELECT c FROM ConfigEventHeader c WHERE c.eventStatusCode = :eventStatusCode"),

    @NamedQuery(name = "ConfigEventHeader.findByComments", query = "SELECT c FROM ConfigEventHeader c WHERE c.comments = :comments"),

    @NamedQuery(name = "ConfigEventHeader.findBySysCreatedBy", query = "SELECT c FROM ConfigEventHeader c WHERE c.sysCreatedBy = :sysCreatedBy"),

    @NamedQuery(name = "ConfigEventHeader.findBySysUpdatedBy", query = "SELECT c FROM ConfigEventHeader c WHERE c.sysUpdatedBy = :sysUpdatedBy"),

    @NamedQuery(name = "ConfigEventHeader.findBySysCreateTime", query = "SELECT c FROM ConfigEventHeader c WHERE c.sysCreateTime = :sysCreateTime"),

    @NamedQuery(name = "ConfigEventHeader.findBySysUpdateTime", query = "SELECT c FROM ConfigEventHeader c WHERE c.sysUpdateTime = :sysUpdateTime")})

public class ConfigEventHeader implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id

    @Basic(optional = false)

    @Column(name = "CONFIG_EVENT_HEADER_PK")

    private Long configEventHeaderPk;

    @Basic(optional = false)

    @Column(name = "BUILD_ID")

    private String buildId;

    @Basic(optional = false)

    @Column(name = "EVENT_STATUS_CODE")

    private String eventStatusCode;

    @Column(name = "COMMENTS")

    private String comments;

    @Column(name = "SYS_CREATED_BY")

    private String sysCreatedBy;

    @Column(name = "SYS_UPDATED_BY")

    private String sysUpdatedBy;

    @Column(name = "SYS_CREATE_TIME")

    @Temporal(TemporalType.TIMESTAMP)

    private Date sysCreateTime;

    @Column(name = "SYS_UPDATE_TIME")

    @Temporal(TemporalType.TIMESTAMP)

    private Date sysUpdateTime;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "configEventHeader")

    private List<ConfigEventUser> configEventUserList;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "configEventHeader")

    private List<ConfigEventDetail> configEventDetailList;

 

    public ConfigEventHeader() {

    }

 

    public ConfigEventHeader(Long configEventHeaderPk) {

        this.configEventHeaderPk = configEventHeaderPk;

    }

 

    public ConfigEventHeader(Long configEventHeaderPk, String buildId, String eventStatusCode) {

        this.configEventHeaderPk = configEventHeaderPk;

        this.buildId = buildId;

        this.eventStatusCode = eventStatusCode;

    }

 

    public Long getConfigEventHeaderPk() {

        return configEventHeaderPk;

    }

 

    public void setConfigEventHeaderPk(Long configEventHeaderPk) {

        this.configEventHeaderPk = configEventHeaderPk;

    }

 

    public String getBuildId() {

        return buildId;

    }

 

    public void setBuildId(String buildId) {

        this.buildId = buildId;

    }

 

    public String getEventStatusCode() {

        return eventStatusCode;

    }

 

    public void setEventStatusCode(String eventStatusCode) {

        this.eventStatusCode = eventStatusCode;

    }

 

    public String getComments() {

        return comments;

    }

 

    public void setComments(String comments) {

        this.comments = comments;

    }

 

    public String getSysCreatedBy() {

        return sysCreatedBy;

    }

 

    public void setSysCreatedBy(String sysCreatedBy) {

        this.sysCreatedBy = sysCreatedBy;

    }

 

    public String getSysUpdatedBy() {

        return sysUpdatedBy;

    }

 

    public void setSysUpdatedBy(String sysUpdatedBy) {

        this.sysUpdatedBy = sysUpdatedBy;

    }

 

    public Date getSysCreateTime() {

        return sysCreateTime;

    }

 

    public void setSysCreateTime(Date sysCreateTime) {

        this.sysCreateTime = sysCreateTime;

    }

 

    public Date getSysUpdateTime() {

        return sysUpdateTime;

    }

 

    public void setSysUpdateTime(Date sysUpdateTime) {

        this.sysUpdateTime = sysUpdateTime;

    }

 

    public List<ConfigEventUser> getConfigEventUserList() {

        return configEventUserList;

    }

 

    public void setConfigEventUserList(List<ConfigEventUser> configEventUserList) {

        this.configEventUserList = configEventUserList;

    }

 

    public List<ConfigEventDetail> getConfigEventDetailList() {

        return configEventDetailList;

    }

 

    public void setConfigEventDetailList(List<ConfigEventDetail> configEventDetailList) {

        this.configEventDetailList = configEventDetailList;

    }

 

    @Override

    public int hashCode() {

        int hash = 0;

        hash += (configEventHeaderPk != null ? configEventHeaderPk.hashCode() : 0);

        return hash;

    }

 

    @Override

    public boolean equals(Object object) {

        // TODO: Warning - this method won't work in the case the id fields are not set

        if (!(object instanceof ConfigEventHeader)) {

            return false;

        }

        ConfigEventHeader other = (ConfigEventHeader) object;

        if ((this.configEventHeaderPk == null && other.configEventHeaderPk != null) || (this.configEventHeaderPk != null && !this.configEventHeaderPk.equals(other.configEventHeaderPk))) {

            return false;

        }

        return true;

    }

 

    @Override

    public String toString() {

        return "dti.admin.cp.entity.ConfigEventHeader[configEventHeaderPk=" + configEventHeaderPk + "]";

    }

 

}

 

persistence.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="ConfigPropsPU" transaction-type="JTA">

        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

        <jta-data-source>jdbc/odev20122</jta-data-source>

        <class>dti.admin.cp.entity.ConfigEventHeader</class>

        <class>dti.admin.cp.entity.ConfigEventDetail</class>

        <class>dti.admin.cp.entity.ConfigEventClob</class>

        <class>dti.admin.cp.entity.ConfigEventDbLink</class>

        <class>dti.admin.cp.entity.ConfigEventDetailSql</class>

        <class>dti.admin.cp.entity.ConfigEventError</class>

        <class>dti.admin.cp.entity.ConfigEventHistory</class>

        <class>dti.admin.cp.entity.ConfigEventMode</class>

        <class>dti.admin.cp.entity.ConfigEventUser</class>

        <class>dti.admin.cp.entity.ConfigEventUtil</class>

        <class>dti.admin.cp.entity.ConfigEventUtilXref</class>

        <class>dti.admin.cp.entity.ConfigEventWarningDetail</class>

        <class>dti.admin.cp.entity.ConfigEventWarningMaster</class>

        <class>dti.admin.cp.entity.ConfigEventWarningSetup</class>

        <properties/>

    </persistence-unit>

</persistence>

 

 

Spring configuration:

    <!-- Add JPA support -->

    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

        <property name="persistenceUnitName" value="ConfigPropsPU"/>

        <property name="jpaVendorAdapter">

            <bean

                class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter ">

            </bean>

        </property>

         <property name="loadTimeWeaver">

            <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>

       </property>    

    </bean>

 

    <!-- Add Transaction support -->

    <bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">

        <property name="entityManagerFactory" ref="emf"/>

    </bean>

 

    <!-- Use @Transaction annotations for managing transactions -->

    <tx:annotation-driven transaction-manager="transactionManager" />

 

 

    <bean id="PersistenceAnnotationBeanPostProcessor" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

 

If I use “loadTimeWeaver” it wouldn’t deploy and throw the following exception:

 

<Feb 17, 2012 12:05:34 PM EST> <Warning> <HTTP> <BEA-101162> <User defined liste

ner dti.core.webapp.OasisContextLoaderListener failed: org.springframework.beans

.factory.BeanCreationException: Error creating bean with name 'configEventHeader

Dao': Injection of persistence dependencies failed; nested exception is org.spri

ngframework.beans.factory.BeanCreationException: Error creating bean with name '

emf' defined in class path resource [dti/applicationContext-ConfigProp.xml]: Inv

ocation of init method failed; nested exception is java.lang.reflect.UndeclaredT

hrowableException.

org.springframework.beans.factory.BeanCreationException: Error creating bean wit

h name 'configEventHeaderDao': Injection of persistence dependencies failed; nes

ted exception is org.springframework.beans.factory.BeanCreationException: Error

creating bean with name 'emf' defined in class path resource [dti/applicationCon

text-ConfigProp.xml]: Invocation of init method failed; nested exception is java

.lang.reflect.UndeclaredThrowableException

        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProc

essor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:341)

 

        at org.springframework.beans.factory.support.AbstractAutowireCapableBean

Factory.populateBean(AbstractAutowireCapableBeanFactory.java:1064)

        at org.springframework.beans.factory.support.AbstractAutowireCapableBean

Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)

        at org.springframework.beans.factory.support.AbstractAutowireCapableBean

Factory.createBean(AbstractAutowireCapableBeanFactory.java:456)

        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb

ject(AbstractBeanFactory.java:291)

        Truncated. see log file for complete stacktrace

Caused By: org.springframework.beans.factory.BeanCreationException: Error creati

ng bean with name 'emf' defined in class path resource [dti/applicationContext-C

onfigProp.xml]: Invocation of init method failed; nested exception is java.lang.

reflect.UndeclaredThrowableException

        at org.springframework.beans.factory.support.AbstractAutowireCapableBean

Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1412)

        at org.springframework.beans.factory.support.AbstractAutowireCapableBean

Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)

        at org.springframework.beans.factory.support.AbstractAutowireCapableBean

Factory.createBean(AbstractAutowireCapableBeanFactory.java:456)

        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb

ject(AbstractBeanFactory.java:291)

        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr

y.getSingleton(DefaultSingletonBeanRegistry.java:222)

        Truncated. see log file for complete stacktrace

Caused By: java.lang.reflect.UndeclaredThrowableException

        at $Proxy69.addTransformer(Unknown Source)

        at org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntity

ManagerFactory(PersistenceProvider.java:234)

        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.cr

eateNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)

        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPro

pertiesSet(AbstractEntityManagerFactoryBean.java:308)

        at org.springframework.beans.factory.support.AbstractAutowireCapableBean

Factory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1469)

        Truncated. see log file for complete stacktrace

Caused By: java.lang.reflect.InvocationTargetException

        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.

java:39)

        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces

sorImpl.java:25)

        at java.lang.reflect.Method.invoke(Method.java:597)

        at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitMan

ager$Jpa2PersistenceUnitInfoDecorator.invoke(DefaultPersistenceUnitManager.java:

431)

        Truncated. see log file for complete stacktrace

Caused By: java.lang.IllegalStateException: Must start with Java agent to use In

strumentationLoadTimeWeaver. See Spring documentation.

        at org.springframework.instrument.classloading.InstrumentationLoadTimeWe

aver.addTransformer(InstrumentationLoadTimeWeaver.java:87)

        at org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo

.addTransformer(SpringPersistenceUnitInfo.java:111)

        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.

java:39)

        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces

sorImpl.java:25)

        Truncated. see log file for complete stacktrace

> 

 

If I comment out the reference to “loadTimeWeaver” I would get the following strange error:

 

Exception Description: Deployment of PersistenceUnit [ConfigPropsPU] failed.

Internal Exception: Exception [EclipseLink-7198] (Eclipse Persistence Services -

2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ValidationException

 

Exception Description: Class: [dti.admin.cp.entity.ConfigEventUser] was not foun

d while converting from class names to classes.

Internal Exception: java.lang.ClassNotFoundException: dti.admin.cp.entity.Config

EventUser

        at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpress

ion.java:114)

        at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.

java:194)

        at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.

java:182)

        at javax.faces.component.UIOutput.getValue(UIOutput.java:169)

        at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(Ht

mlBasicInputRenderer.java:205)

        Truncated. see log file for complete stacktrace

Caused By: javax.persistence.PersistenceException: Exception [EclipseLink-28019]

(Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistenc

e.exceptions.EntityManagerSetupException

Exception Description: Deployment of PersistenceUnit [ConfigPropsPU] failed.

Internal Exception: Exception [EclipseLink-7198] (Eclipse Persistence Services -

2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ValidationException

 

Exception Description: Class: [dti.admin.cp.entity.ConfigEventUser] was not foun

d while converting from class names to classes.

Internal Exception: java.lang.ClassNotFoundException: dti.admin.cp.entity.Config

EventUser

        at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(En

tityManagerSetupImpl.java:460)

        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.get

DatabaseSession(EntityManagerFactoryDelegate.java:188)

        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.cre

ateEntityManagerImpl(EntityManagerFactoryDelegate.java:277)

        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createE

ntityManagerImpl(EntityManagerFactoryImpl.java:294)

        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createE

ntityManager(EntityManagerFactoryImpl.java:272)

        Truncated. see log file for complete stacktrace

Caused By: Exception [EclipseLink-28019] (Eclipse Persistence Services - 2.3.2.v

20111125-r10461): org.eclipse.persistence.exceptions.EntityManagerSetupException

 

Exception Description: Deployment of PersistenceUnit [ConfigPropsPU] failed.

Internal Exception: Exception [EclipseLink-7198] (Eclipse Persistence Services -

2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ValidationException

 

Exception Description: Class: [dti.admin.cp.entity.ConfigEventUser] was not foun

d while converting from class names to classes.

Internal Exception: java.lang.ClassNotFoundException: dti.admin.cp.entity.Config

EventUser

        at org.eclipse.persistence.exceptions.EntityManagerSetupException.deploy

Failed(EntityManagerSetupException.java:229)

        at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(En

tityManagerSetupImpl.java:460)

        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.get

DatabaseSession(EntityManagerFactoryDelegate.java:188)

        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.cre

ateEntityManagerImpl(EntityManagerFactoryDelegate.java:277)

        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createE

ntityManagerImpl(EntityManagerFactoryImpl.java:294)

        Truncated. see log file for complete stacktrace

Caused By: Exception [EclipseLink-7198] (Eclipse Persistence Services - 2.3.2.v2

0111125-r10461): org.eclipse.persistence.exceptions.ValidationException

Exception Description: Class: [dti.admin.cp.entity.ConfigEventUser] was not foun

d while converting from class names to classes.

Internal Exception: java.lang.ClassNotFoundException: dti.admin.cp.entity.Config

EventUser

        at org.eclipse.persistence.exceptions.ValidationException.classNotFoundW

hileConvertingClassNames(ValidationException.java:2341)

        at org.eclipse.persistence.mappings.ForeignReferenceMapping.convertClass

NamesToClasses(ForeignReferenceMapping.java:371)

        at org.eclipse.persistence.mappings.CollectionMapping.convertClassNamesT

oClasses(CollectionMapping.java:854)

        at org.eclipse.persistence.descriptors.ClassDescriptor.convertClassNames

ToClasses(ClassDescriptor.java:1534)

        at org.eclipse.persistence.sessions.Project.convertClassNamesToClasses(P

roject.java:432)

        Truncated. see log file for complete stacktrace

Caused By: java.lang.ClassNotFoundException: dti.admin.cp.entity.ConfigEventUser

 

        at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(Generic

ClassLoader.java:297)

        at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClass

Loader.java:270)

        at weblogic.utils.classloaders.ChangeAwareClassLoader.findClass(ChangeAw

areClassLoader.java:64)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

        Truncated. see log file for complete stacktrace

> 

 

 

Do you know what is wrong with my configuration?

 

Best regards,

 

 

Michael Gitelman

mgitelman@xxxxxxxxxxxxxxx

 

Delphi Technology, Inc.

One Washington Mall, Suite 3

Boston, MA  02108

O: 617 259 1256

F: 617 778 2296

www.delphi-tech.com

 

Experience, Innovation... Results.


Back to the top