If I define the objects in XML and call var xmlApplicationContext = new XmlApplicationContext() the job is scheduled and fires. What I would like to accomplish is to do this through code as the properties will be dynamic, the method fragment below compiles and runs but the job is not scheduled. Is this possible?
// SpringJob.xml
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<object name="emailNotification" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz">
<property name="JobType" value="Project.Agent.Jobs.EmailNotification, Project.Agent" />
</object>
<object id="simpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz">
<property name="jobDetail" ref="emailNotification" />
<property name="startDelay" value="1s" />
<property name="repeatInterval" value="1s" />
<property name="repeatCount" value="0" />
</object>
<object type="Spring.Scheduling.Quartz.SchedulerFactoryObject, Spring.Scheduling.Quartz">
<property name="triggers">
<list>
<ref object="simpleTrigger" />
</list>
</property>
</object>
</objects>
// Method
var jobDetailObject = new JobDetailObject
{
JobType = new EmailNotification().GetType()
};
var simpleTrigger = new SimpleTriggerObject
{
JobDetail = jobDetailObject,
StartDelay = new TimeSpan(0, 0, 0, 1),
RepeatInterval = new TimeSpan(0, 0, 0, 1),
RepeatCount = 0
};
var scheduleTrigger = new SchedulerFactoryObject();
var triggers = new Trigger[1];
triggers[0] = simpleTrigger;
scheduleTrigger.Triggers = triggers;
scheduleTrigger.Start();
Decided to abandon the Spring.Net framework implementation of Quartz.Net instead I am using Quartz.Net directly.
Related
I'm building a OData service using the ODataLib v7.1.1 bits from Microsoft.OData.Core (et al). I'm having trouble using the shortened key predicate URL format with ODataUriParser.ParsePath(). The (relative) URL "Company('Comp1')/Customer(1)" throws an exception "The number of keys specified in the URI does not match number of key properties for the resource 'Test.Customer'".
The model is very simple and I can't see why this isn't working. Other formats for the URLs work ("Company('Comp1')", "Customer(CompanyId='COMP1',CustNum=1)").
I've put the model builder code below along with the $metadata output. Any help would be appreciated. Thanks!
-Erik
var result = new EdmModel();
var company = new EdmEntityType("Test", "Company");
var companyKey1 = company.AddStructuralProperty("CompanyId", EdmPrimitiveTypeKind.String, false);
company.AddKeys(
companyKey1
);
result.AddElement(company);
var customer = new EdmEntityType(NS, "Customer");
var customerKey1 = customer.AddStructuralProperty("CompanyId", EdmPrimitiveTypeKind.String, false);
var customerKey2 = customer.AddStructuralProperty("CustNum", EdmPrimitiveTypeKind.Int32, false);
customer.AddKeys(
customerKey1,
customerKey2
);
result.AddElement(customer);
var navCompanyCustomer = company.AddUnidirectionalNavigation(
new EdmNavigationPropertyInfo()
{
ContainsTarget = true,
Name = "Customer",
Target = customer,
TargetMultiplicity = EdmMultiplicity.Many
});
var customerRefToCompany = customer.AddUnidirectionalNavigation(
new EdmNavigationPropertyInfo()
{
ContainsTarget = false,
Name = "Company",
Target = company,
TargetMultiplicity = EdmMultiplicity.One,
DependentProperties = new[] { customerKey1 },
PrincipalProperties = new[] { companyKey1 }
});
var container = new EdmEntityContainer("Test", "DefaultContainer");
result.AddElement(container);
container.AddEntitySet("Company", company);
container.AddEntitySet("Customer", customer);
return result;
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema Namespace="Test" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="Company">
<Key>
<PropertyRef Name="CompanyId" />
</Key>
<Property Name="CompanyId" Type="Edm.String" Nullable="false" />
<NavigationProperty Name="Customer" Type="Collection(Test.Customer)" ContainsTarget="true" />
</EntityType>
<EntityType Name="Customer">
<Key>
<PropertyRef Name="CompanyId" />
<PropertyRef Name="CustNum" />
</Key>
<Property Name="CompanyId" Type="Edm.String" Nullable="false" />
<Property Name="CustNum" Type="Edm.Int32" Nullable="false" />
<NavigationProperty Name="Company" Type="Test.Company" Nullable="false">
<ReferentialConstraint Property="CompanyId" ReferencedProperty="CompanyId" />
</NavigationProperty>
</EntityType>
<EntityContainer Name="DefaultContainer">
<EntitySet Name="Company" EntityType="Test.Company" />
<EntitySet Name="Customer" EntityType="Test.Customer" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
I figured it out. I had the Dependent / Principal properties reversed (corrected code is below). One of the big debates (years ago) was which way the arrow should point on an RI declaration in entity-relationship model (i.e. which side is dependent). I must of been on the losing side of that one. ;)
var navCompanyCustomer = company.AddUnidirectionalNavigation(
new EdmNavigationPropertyInfo()
{
ContainsTarget = true,
Name = "Customer",
Target = customer,
TargetMultiplicity = EdmMultiplicity.Many,
DependentProperties = new[] { companyKey1 },
PrincipalProperties = new[] { customerKey1 }
});
With the help of the RESTier team, I manage to create an RESTier function that return a list of my entity.
Here's the code
protected EdmModel OnModelExtending(EdmModel model)
{
var ns = model.DeclaredNamespaces.First(); // PointLoc.Data
var entityContainer = (EdmEntityContainer) model.EntityContainer;
var locationEntityType = (IEdmEntityType) model.FindDeclaredType(ns + "." + "Location");
var locationEntitySet = entityContainer.FindEntitySet("Locations");
var locationEntityTypeReference = new EdmEntityTypeReference(locationEntityType, false);
var locationEntityCollection = EdmCoreModel.GetCollection(locationEntityTypeReference);
var ambilLocationsByMarketId = new EdmFunction(ns, "AmbilLocationsByMarketId", locationEntityCollection, false, null, true);
model.AddElement(ambilLocationsByMarketId);
entityContainer.AddFunctionImport("AmbilLocationsByMarketId", ambilLocationsByMarketId,
new EdmEntitySetReferenceExpression(locationEntitySet));
return model;
}
And here's my implementation on the Controller
[HttpGet]
[EnableQuery]
[ODataRoute("AmbilLocationsByMarketId")]
public IQueryable<Location> AmbilLocationsByMarketId()
{
var locations = DbContext.Locations.Where(l => l.Name.Contains("Hotel")).Select(l => l);
return locations;
}
It works fine returning the list of data with i send a HTTP GET to
http://localhost:21922/odata/AmbilLocationsByMarketId
but when I try to add $expand or $filter, It's not working.
http://localhost:21922/odata/AmbilLocationsByMarketId?$expand=Category
I'm Error that reads like
{
"error": {
"code": "",
"message": "An error has occurred.",
"innererror": {
"message": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal'.",
"type": "System.InvalidOperationException",
"stacktrace": "",
"internalexception": {
"message": "'DbQuery`1' cannot be serialized using the ODataMediaTypeFormatter.",
"type": "System.Runtime.Serialization.SerializationException",
"stacktrace": " at System.Web.OData.Formatter.ODataMediaTypeFormatter.GetSerializer(Type type, Object value, IEdmModel model, ODataSerializerProvider serializerProvider)\\\r\\\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\\\r\\\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\\\r\\\n--- End of stack trace from previous location where exception was thrown ---\\\r\\\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\\\r\\\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\\\r\\\n at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\\\r\\\n at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()"
}
}
}
}
Here's my metadata
<EntityType Name="Location">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false">
<Annotation Term="Org.OData.Core.V1.Computed" Bool="true" />
</Property>
<Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="500" />
<Property Name="Address" Type="Edm.String" Nullable="false" MaxLength="2000" />
<Property Name="City" Type="Edm.String" MaxLength="500" />
<Property Name="Postcode" Type="Edm.String" MaxLength="100" />
<Property Name="Phone" Type="Edm.String" MaxLength="50" />
<Property Name="Email" Type="Edm.String" MaxLength="200" />
<Property Name="Latitude" Type="Edm.Decimal" Nullable="false" Precision="9" Scale="6" />
<Property Name="Longitude" Type="Edm.Decimal" Nullable="false" Precision="9" Scale="6" />
<Property Name="Street" Type="Edm.String" MaxLength="1000" />
<Property Name="UpVotes" Type="Edm.Int32" Nullable="false" />
<Property Name="DownVotes" Type="Edm.Int32" Nullable="false" />
<Property Name="CategoryId" Type="Edm.Int32" Nullable="false" />
<Property Name="StatusId" Type="Edm.Int32" Nullable="false" />
<Property Name="StateId" Type="Edm.Int32" Nullable="false" />
<Property Name="TitleSlug" Type="Edm.String" MaxLength="200" />
<NavigationProperty Name="Category" Type="PointLoc.Data.Category" Nullable="false" Partner="Locations">
<ReferentialConstraint Property="CategoryId" ReferencedProperty="Id" />
</NavigationProperty>
</EntityType>
and here's the EntityContainer
<EntityContainer Name="DatabaseContext">
<EntitySet Name="Categories" EntityType="PointLoc.Data.Category">
<NavigationPropertyBinding Path="Locations" Target="Locations" />
</EntitySet>
<EntitySet Name="Locations" EntityType="PointLoc.Data.Location">
<NavigationPropertyBinding Path="Accesses" Target="Accesses" />
<NavigationPropertyBinding Path="Category" Target="Categories" />
<NavigationPropertyBinding Path="Contents" Target="Contents" />
<NavigationPropertyBinding Path="State" Target="States" />
<NavigationPropertyBinding Path="Status" Target="Status" />
<NavigationPropertyBinding Path="LocationMarketMaps" Target="LocationMarketMaps" />
<NavigationPropertyBinding Path="LocationTagMaps" Target="LocationTagMaps" />
</EntitySet>
<FunctionImport Name="AmbilLocationsByMarketId" Function="PointLoc.Data.AmbilLocationsByMarketId" EntitySet="Locations" />
</EntityContainer>
I cant proceed further into my project because of an strange error. I am trying to implement spring-security and spring data JPA for my application, which exposes only REST api.
Now, when I am trying to implement my custom UserDetailsService class, as mentioned below, the parameter username in method loadUserByUsername is not the username I am passing as a POST request parameter, rather its the client_id parameter.
Can someone please suggest as what am I doing wrong?
public class CustomUserDetailsService implements UserDetailsService {
private ClientDetailsService clientDetailsService;
private String emptyPassword = "";
public CustomUserDetailsService() {
}
public CustomUserDetailsService(ClientDetailsService clientDetailsService) {
this.clientDetailsService = clientDetailsService;
}
private List<GrantedAuthority> getAuthorities(String role) {
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
// you can also add different roles here
// for example, the user is also an admin of the site, then you can add
// ROLE_ADMIN
// so that he can view pages that are ROLE_ADMIN specific
if (role != null && role.trim().length() > 0) {
if (role.equals("admin")) {
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
}
return authList;
}
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
ClientDetails clientDetails = clientDetailsService
.loadClientByClientId(username);
String clientSecret = clientDetails.getClientSecret();
if (clientSecret == null || clientSecret.trim().length() == 0) {
clientSecret = emptyPassword;
}
return new User(username, clientSecret, clientDetails.getAuthorities());
}
}
My spring-security configuration is as following:
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd ">
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/api/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/logout" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/logout" method="GET" />
<sec:logout invalidate-session="true" logout-url="/logout"
success-handler-ref="logoutSuccessHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="logoutSuccessHandler" class="com.monsor.feasthub.security.LogoutImpl">
<property name="tokenstore" ref="tokenStore" />
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />
<bean id="applicationContextProvder" class="com.monsor.feasthub.util.ApplicationContextProvider" />
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService" class="com.monsor.feasthub.security.CustomUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="com.monsor.feasthub.security.ClientDetailsServiceImpl" />
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password authentication-manager-ref="userAuthenticationManager" />
</oauth:authorization-server>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="customUserAuthenticationProvider" />
</authentication-manager>
<bean id="customUserAuthenticationProvider"
class="com.monsor.feasthub.security.CustomUserAuthenticationProvider" />
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="300000" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<mvc:annotation-driven /> <!-- Declares explicit support for annotation-driven MVC controllers #RequestMapping,
#Controller -->
<mvc:default-servlet-handler />
<bean id="MyResource" class="com.monsor.feasthub.resources.MyResource" />
</beans>
I tried to parse an xml file to flatefile. All worked fine except at the end. In debug Mode the cause of the infinite loop is due to the method moveCursorToNextFragment( reader) in org.springframework.batch.item.xml.StaxEventItemRe ader.class.
More precisily in this part of method
while (reader.peek() != null && !reader.peek().isStartElement()) {
reader.nextEvent();
}
it seems that these conditions are not sufficient to recognize the end of the document.
I replace this part of code by this code to be sure the end of the document test
while (reader.peek() != null && !reader.peek().isStartElement() && !reader.peek().isEndDocument()) {
reader.nextEvent();
}
if (reader.peek() == null || reader.peek().isEndDocument()) {
return false;
}
below my context file and the link for an INSEE xmlfile : http://lei-france.insee.fr/Telechargement.do
I always taked the full file.
Here is my context file
<?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:batch="http://www.springframework.org/schema/batch"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher"
p:jobRepository-ref="jobRepository"
p:taskExecutor-ref="taskExecutor" />
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
p:dataSource-ref="dataSource"
p:transactionManager-ref="transactionManager" />
<bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
<!-- DATASOURCE -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:#gulli:1521:OPE" />
<property name="username" value="xxxxxx" />
<property name="password" value="xxx" />
</bean>
<!-- ITEM READER -->
<bean id="itemReader" scope="step" class="org.springframework.batch.item.xml.StaxEventItemReader"
p:resource="insee/lei.xml"
p:fragmentRootElementName="LEIRecord"
p:unmarshaller-ref="inseeMarshaller" />
<bean id="inseeMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"
p:autodetectAnnotations="true" p:encoding="UTF-8">
<property name="aliases">
<props>
<prop key="LEIDirectory">fr.cdn.dtc.etudes.emir.insee.LEIDirectory</prop>
<prop key="LEIRecord">fr.cdn.dtc.etudes.emir.insee.LEIRecord</prop>
<prop key="LegalEntity">fr.cdn.dtc.etudes.emir.insee.LegalEntity</prop>
<prop key="OtherIdentifiers">fr.cdn.dtc.etudes.emir.insee.OtherIdentifiers</prop>
<prop key="OtherNames">fr.cdn.dtc.etudes.emir.insee.OtherNames</prop>
<prop key="RelatedLEI">fr.cdn.dtc.etudes.emir.insee.RelatedLEI</prop>
<prop key="Event">fr.cdn.dtc.etudes.emir.insee.Event</prop>
<prop key="OtherAddresses">fr.cdn.dtc.etudes.emir.insee.OtherAddresses</prop>
</props>
</property>
</bean>
<!-- ITEM WRITER DELIMETED LENGTH-->
<bean id="itemWriterFile" class="org.springframework.batch.item.file.FlatFileItemWriter"
p:resource-ref="outputDelimitedResource"
p:lineAggregator-ref="lineAggregator"
p:shouldDeleteIfExists="true"
/>
<bean id="outputDelimitedResource" class="org.springframework.core.io.FileSystemResource">
<constructor-arg value="target/outputs/inseeOutput.txt" />
</bean>
<bean id="lineAggregator" class="org.springframework.batch.item.file.transform.DelimitedLineAggregator"
p:delimiter=";"
p:fieldExtractor-ref="fieldExtractor" />
<bean id="fieldExtractor" class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor"
p:names="le" />
<batch:job id="inseeJob" job-repository="jobRepository" >
<batch:step id="inseeStep">
<batch:tasklet>
<batch:chunk reader="itemReader" writer="itemWriterFile" commit-interval="10" />
<batch:transaction-attributes isolation="DEFAULT" propagation="REQUIRED" timeout="30"/>
</batch:tasklet>
</batch:step>
</batch:job>
</beans>
Best Regards
Clément
Can somebody please help me with this error. I have an ASP.NET WebApp, within the Entity Model I have an entity called tb_AdminUser, with a UserID property as GUID. This is also the Entity Key. The entity is not in any relationship with any other entity. I get the error when calling the AddObject() function.
In my code I call the following...
SQL2008R2_824852_leapdbEntities temp = new SQL2008R2_824852_leapdbEntities();
tb_AdminUser au = new tb_AdminUser();
au.UserID = Guid.NewGuid();
au.Username = "TEST";
au.Password = "pete#webinspired.net";
au.LockedOut = false;
au.Surname = "Feehan";
au.Forename = "Pete";
temp.tb_AdminUser.AddObject(au); //error occurs here
temp.SaveChanges();
The EDMX XML Code is as follows
<EntityType Name="tb_AdminUser">
<Key>
<PropertyRef Name="UserID" />
</Key>
<Property Name="UserID" Type="uniqueidentifier" Nullable="false" />
<Property Name="Forename" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Surname" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Username" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Password" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="LockedOut" Type="bit" Nullable="false" />
</EntityType>