Hi Thiago, I don't believe I"m doing anything out of the ordinary or rather
anything different than I've ever done on any other project. Please take a
look at the code below and see if you notice anything that stands out.
Thanks in advance.

My usage.

*SupportContract*.tml

<t:form t:id="form" class="form-horizontal">
        <t:errors/>
        <t:AjaxFormLoop t:id="supportContract"
source="property.companyContracts" value="companyContract"
addRow="block:addRowContract" encoder="encoderContract" show="show">
            <div class="form-group">
                <t:label for="serviceType"  class="col-sm-2 control-label"/>
                <div  class="col-sm-8">
                    <t:Select t:id="serviceType"
value="companyContract.supportContract" model="supportContractModel"
t:secure="literal:NEVER" blankOption="always" blankLabel="literal:Select
Service" class="form-control input-sm"/>
                </div>
            </div>
            <div t:type="if" test="companyContract.id" class="form-group">
                <div class="col-sm-offset-2 col-sm-8">
                    <div
class="float-right"><t:removerowlink>remove</t:removerowlink></div>
                </div>
            </div>
        </t:AjaxFormLoop>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-8">
                <t:Submit value="Save" class="btn btn-primary"/>
                <t:PageLink page="index" class="btn">Cancel</t:PageLink>
            </div>
        </div>
    </t:form>

SupportContract.java


@RequiresUser
public class *SupportContract* {

    @Component(id = "form")
    private Form form;

    private CompanyContract companyContract;

    @Inject
    private Session session;

    @Property
    private Company property;

    @Inject
    private CrudServiceDAO crudServiceDAO;

    @Inject
    private SelectModelFactory selectModelFactory;

    @Inject
    private Request request;

    private EventContext eventContext;

    private boolean formSubmit;

    public Class<?> onActivate(EventContext eventContext) {
        formSubmit = false;

        try {
            if (!request.isXHR()) {
                Integer id = eventContext.get(Integer.class, 0);

                property = (Company) session.get(Company.class, id);

                if(property == null) {
                    property = new Company();
                }
            }
            this.eventContext = eventContext;
        } catch (Exception ex) {
            return Index.class;
        }
        return null;
    }

    public Object onPassivate() {
        return eventContext.toStrings();
    }

    void onPrepareForSubmit() {
        formSubmit = true;
    }

    void onValidateFromForm() {
        if(companyContract != null && companyContract.getSupportContract()
== null) {
            form.recordError("Fail");
        }
    }

    @CommitAfter
    void onSuccess() {
        session.saveOrUpdate(property);
    }

    CompanyContract onAddRow() {
        return new CompanyContract();
    }

    public CompanyContract getCompanyContract() {
        return companyContract;
    }

    public void setCompanyContract(CompanyContract companyContract) {
        this.companyContract = companyContract;

        if(formSubmit) {
            property.getCompanyContracts().add(companyContract);
        }
    }

    @SuppressWarnings("unchecked")
    public ValueEncoder getEncoderContract() {
        return new ValueEncoder<CompanyContract>() {

            @Override
            public String toClient(CompanyContract value) {
                Integer id = value.getId();
                return id != null ? id.toString() : null;
            }

            @Override
            public CompanyContract toValue(String toValue) {
                if(toValue != null) {
                    Integer id = Integer.parseInt(toValue);
                    return (CompanyContract)
session.get(CompanyContract.class, id);
                }
                return new CompanyContract(property);
            }
        };
    }

    public SelectModel getSupportContractModel() {
        List<SupportContract> supportContracts =
session.criteriaQuery(SupportContract.class).list()
        return selectModelFactory.create(supportContracts, "name");
    }

}

Company.class Entity (I use property variable)

@Entity
@Table(name = "company")
@Indexed
@AnalyzerDef(name = "customanalyzer",
        tokenizer
        = @TokenizerDef(factory = StandardTokenizerFactory.class),
        filters = {
            @TokenFilterDef(factory = LowerCaseFilterFactory.class),})
public class *Company* extends BaseEntity {

    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL,
orphanRemoval = true)
    private List<CompanyContract> companyContracts;

    public List<CompanyContract> getCompanyContracts() {
        if (companyContracts == null) {
            companyContracts = new ArrayList<>();
        }
        return companyContracts;
    }

    public void setCompanyContracts(List<CompanyContract> companyContracts)
{
        this.companyContracts = companyContracts;
    }

}

CompanyContact.class Entity


@Entity
public class *CompanyContract* extends BaseEntity {

    @Validate("required")
    @ManyToOne
    @JoinColumn(name = "support_contract_id", nullable = false)
    private SupportContract supportContract;

    @Validate("required")
    @ManyToOne
    @JoinColumn(name = "company_id", nullable = false)
    private Company company;

    public CompanyContract() {
    }

    public CompanyContract(Company company) {
        this.company = company;
    }

    public void setSupportContract(SupportContract supportContract) {
        this.supportContract = supportContract;
    }

    public SupportContract getSupportContract() {
        return supportContract;
    }

    public void setSupportContract(SupportContract supportContract) {
        this.supportContract = supportContract;
    }

}

@Entity
public class *SupportContract* extends BaseEntity {

    @Column(nullable = false, length = 255)
    @Validate("maxlength=255")
    private String name;

    @OneToMany(mappedBy = "supportContract")
    private List<CompanyContract> companyContracts;

    public SupportContract() {
    }

    public List<CompanyContract> getCompanyContracts() {
        return companyContracts;
    }

    public void setCompanyContracts(List<CompanyContract> companyContracts)
{
        this.companyContracts = companyContracts;
    }

    public String getName() {
        return name;
    }

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

}

*Hibernate.cfg.xml*

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate
Configuration DTD 3.0//EN" "
http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd";>
<hibernate-configuration>
    <session-factory>
        <property
name="hibernate.connection.datasource">jdbc/domain</property>
<!--        <property
name="hibernate.connection.datasource">java:comp/env/jdbc/domain</property>-->
        <property name="hbm2ddl.auto">validate</property>

        <property
name="hibernate.search.default.directory_provider">filesystem</property>
        <property
name="hibernate.search.default.indexBase">/users/george/Documents/indexes
</property>

        <property name="hibernate.format_sql">false</property>
        <property name="hibernate.show_sql">true</property>

    </session-factory>
</hibernate-configuration>


*public class AppModule {*

    private static final String EXCEPTION_HANDLE_METHOD_NAME =
"handleRequestException";
    // TODO: Replace with true value
    public static final String APP_ENV = "APP_ENV";

    public static void bind(ServiceBinder binder) {
        try {
            ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
            List<Class<?>> daos =
PackageEnumerator.getClassesForPackage("com.communication.mydeepblue.dao");
            for (Class<?> dao : daos) {
                String pkg = dao.getPackage().getName();
                String cls = dao.getSimpleName();
                try {
                    Class impl = contextClassLoader.loadClass(pkg +
".impl." + cls + "Impl");
                    binder.bind(dao, impl);
                } catch (ClassNotFoundException e) {
                    // Ignore, we just won't bind that class.
                }
            }
        } catch (ClassNotFoundException e) {

java.util.logging.Logger.getLogger(AppModule.class.getName()).log(Level.SEVERE,
"AppModule error binding: ", e);
        }

        //Services
        binder.bind(UserProfileService.class, UserProfileServiceImpl.class);
        binder.bind(SearchService.class, SearchServiceImpl.class);


        binder.bind(ProductionExceptionHandlerServiceImpl.class);
        binder.bind(SchedulerService.class, SchedulerServiceImpl.class);
        binder.bind(FileAttachmentService.class,
FileAttachmentServiceImpl.class);
        binder.bind(RemoveRowFromAddRow.class,
RemoveRowFromAddRowImpl.class);
        binder.bind(ProductionExceptionHandlerService.class,
ProductionExceptionHandlerServiceImpl.class);
        binder.bind(KayakoWebService.class, KayakoWebServiceImpl.class);

        binder.bind(CompanyResourceImpl.class, CompanyResourceImpl.class);
        binder.bind(JerseyClientPost.class, JerseyClientPostImpl.class);

        binder.bind(RoleManagerService.class, RoleManagerServiceImpl.class);
    }

    public static void contributeFactoryDefaults(
            MappedConfiguration<String, Object> configuration) {
        // The application version is incorprated into URLs for most
assets. Web
        // browsers will cache assets because of the far future expires
header.
        // If existing assets change (or if the Tapestry version changes)
you
        // should also change this number, to force the browser to download
new
        // versions. This overrides Tapesty's default (a random hexadecimal
        // number), but may be further overriden by DevelopmentModule or
QaModule
        // by adding the same key in the contributeApplicationDefaults
method.
        configuration.override(SymbolConstants.APPLICATION_VERSION,
"2.0-SNAPSHOT");
        configuration.override(SymbolConstants.PRODUCTION_MODE, false);
    }

    public static void contributeApplicationDefaults(
            MappedConfiguration<String, Object> configuration) {
        // Contributions to ApplicationDefaults will override any
contributions to
        // FactoryDefaults (with the same key). Here we're restricting the
supported
        // locales to just "en" (English). As you add localised message
catalogs and other assets,
        // you can extend this list of locales (it's a comma separated
series of locale names;
        // the first locale name is the default when there's no reasonable
match).
        configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en");
    }

    /**
     * Use annotation or method naming convention:
     * <code>contributeApplicationDefaults</code>
     */
    @Contribute(SymbolProvider.class)
    @ApplicationDefaults
    public static void setupEnvironment(MappedConfiguration<String, Object>
configuration) {

configuration.add(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER,
"jquery");
        configuration.add(SymbolConstants.HMAC_PASSPHRASE, "mydeepblue");
//        configuration.add(SymbolConstants.MINIFICATION_ENABLED, true);

        // Tynamo tapestry-security configuration
        configuration.add(SecuritySymbols.LOGIN_URL, "/login");
        configuration.add(SecuritySymbols.UNAUTHORIZED_URL, "/restricted");

//
 
ProductionMode.getInstance().setIsProduction(!"DEV".equals(System.getenv(APP_ENV)));
    }

    /*
     // This will override the bundled bootstrap version and will compile
it at runtime
     @Contribute(JavaScriptStack.class)
     @Core
     public static void
overrideBootstrapCSS(OrderedConfiguration<StackExtension> configuration)
     {
     configuration.override("bootstrap.css",
     new StackExtension(StackExtensionType.STYLESHEET,
"context:mybootstrap/css/bootstrap.css"), "before:tapestry.css");
     }
     */
    /**
     * This is a service definition, the service will be named
"TimingFilter".
     * The interface, RequestFilter, is used within the RequestHandler
service
     * pipeline, which is built from the RequestHandler service
configuration.
     * Tapestry IoC is responsible for passing in an appropriate Logger
     * instance. Requests for static resources are handled at a higher
level, so
     * this filter will only be invoked for Tapestry related requests.
     * <p/>
     * <p/>
     * Service builder methods are useful when the implementation is inline
as
     * an inner class (as here) or require some other kind of special
     * initialization. In most cases, use the static bind() method instead.
     * <p/>
     * <p/>
     * If this method was named "build", then the service id would be taken
from
     * the service interface and would be "RequestFilter". Since Tapestry
     * already defines a service named "RequestFilter" we use an explicit
     * service id that we can reference inside the contribution method.
     */
    public RequestFilter buildTimingFilter(final Logger log) {
        return new RequestFilter() {
            public boolean service(Request request, Response response,
RequestHandler handler)
                    throws IOException {
                long startTime = System.currentTimeMillis();

                try {
                    // The responsibility of a filter is to invoke the
corresponding method
                    // in the handler. When you chain multiple filters
together, each filter
                    // received a handler that is a bridge to the next
filter.

                    return handler.service(request, response);
                }
                finally {
                    long elapsed = System.currentTimeMillis() - startTime;

                    log.info(String.format("Request time: %d ms", elapsed));
                }
            }
        };
    }

    /**
     * This is a contribution to the RequestHandler service configuration.
This
     * is how we extend Tapestry using the timing filter. A common use for
this
     * kind of filter is transaction management or security. The @Local
     * annotation selects the desired service by type, but only from the
same
     * module. Without @Local, there would be an error due to the other
     * service(s) that implement RequestFilter (defined in other modules).
     */
    public void
contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
            @Local RequestFilter filter) {
        // Each contribution to an ordered configuration has a name, When
necessary, you may
        // set constraints to precisely control the invocation order of the
contributed filter
        // within the pipeline.

        configuration.add("Timing", filter);
    }

    /**
     * Contributions to the RESTeasy main Application, insert all your
RESTeasy
     * singletons services here.
     */
    @Contribute(Application.class)
    public static void configureRestResources(Configuration<Object>
singletons, CompanyResource companyResource) {
        singletons.add(companyResource);
    }

    @Startup
    public static void initApplication(SchedulerService scheduler) {
        scheduler.init();
    }

    public static void
contributeHibernateSessionSource(OrderedConfiguration<HibernateConfigurer>
configuration) {
        configuration.addInstance("DeepBlue",
DeepBlueHibernateConfigurer.class);
    }

    public static void contributeWebSecurityManager(Configuration<Realm>
configuration, @Autobuild DeepBlueRealm realm) {
        configuration.add(realm);
    }


    @Match("*DAO")
    public static void adviseTransactions(HibernateTransactionAdvisor
advisor, MethodAdviceReceiver receiver) {
        advisor.addTransactionCommitAdvice(receiver);
    }

    public static void
contributeResteasyPackageManager(org.apache.tapestry5.ioc.Configuration<String>
configuration) {
        configuration.add("org.tynamo.resteasy.ws");
    }

    @Scope(ScopeConstants.PERTHREAD)
    public static FullTextSession
buildFullTextSession(HibernateSessionManager sessionManager) {
        return Search.getFullTextSession(sessionManager.getSession());
    }

    @Startup
    public static void initApplication(FullTextSession fullTextSession)
throws InterruptedException {
        fullTextSession.createIndexer().startAndWait();
    }
}


*DeepBlueHibernateConfigurer.class *

public class DeepBlueHibernateConfigurer implements HibernateConfigurer {

    public void configure(Configuration configuration) {
        configuration.setNamingStrategy(ImprovedNamingStrategy.INSTANCE);
    }
}


On Thu, Dec 19, 2013 at 5:57 AM, Thiago H de Paula Figueiredo <
[email protected]> wrote:

> On Thu, 19 Dec 2013 05:27:19 -0200, George Christman <
> [email protected]> wrote:
>
>  While trying to submit a new record with blankOption="always" and
>> t:secure="literal:NEVER" I'm finding when my getModel method is
>> called, the query used to rebuild my select model attempts to commit
>> my object model to the database resulting in a database constraint
>> violation exception rather than throw back a validation error.
>>
>
> Are you sure the code that triggers the database insertion isn't yours?
>
> This looks more like bad usage of Hibernate in your side than a Tapestry
> error, but without all the corresponding code there's no way to be sure.
>
>
>  Now I'm not sure if this really matters, but I am using this select
>> component within an ajaxformloop.
>>
>
> Maybe. You didn't post the code of your AjaxFormLoop event handler methods
> nor the ValueEncoder you're using (if it's not the one automatically
> provided by tapestry-hibernate).
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>


-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Reply via email to